PageRenderTime 50ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/fzaninotto/faker/src/Faker/Provider/Base.php

https://gitlab.com/judielsm/Handora
PHP | 509 lines | 283 code | 35 blank | 191 comment | 29 complexity | fa344af6bb81161ba8951618501d4523 MD5 | raw file
  1. <?php
  2. namespace Faker\Provider;
  3. use Faker\Generator;
  4. use Faker\DefaultGenerator;
  5. use Faker\UniqueGenerator;
  6. class Base
  7. {
  8. /**
  9. * @var \Faker\Generator
  10. */
  11. protected $generator;
  12. /**
  13. * @var \Faker\UniqueGenerator
  14. */
  15. protected $unique;
  16. /**
  17. * @param \Faker\Generator $generator
  18. */
  19. public function __construct(Generator $generator)
  20. {
  21. $this->generator = $generator;
  22. }
  23. /**
  24. * Returns a random number between 0 and 9
  25. *
  26. * @return integer
  27. */
  28. public static function randomDigit()
  29. {
  30. return mt_rand(0, 9);
  31. }
  32. /**
  33. * Returns a random number between 1 and 9
  34. *
  35. * @return integer
  36. */
  37. public static function randomDigitNotNull()
  38. {
  39. return mt_rand(1, 9);
  40. }
  41. /**
  42. * Returns a random integer with 0 to $nbDigits digits.
  43. *
  44. * The maximum value returned is mt_getrandmax()
  45. *
  46. * @param integer $nbDigits Defaults to a random number between 1 and 9
  47. * @param boolean $strict Whether the returned number should have exactly $nbDigits
  48. * @example 79907610
  49. *
  50. * @return integer
  51. */
  52. public static function randomNumber($nbDigits = null, $strict = false)
  53. {
  54. if (!is_bool($strict)) {
  55. throw new \InvalidArgumentException('randomNumber() generates numbers of fixed width. To generate numbers between two boundaries, use numberBetween() instead.');
  56. }
  57. if (null === $nbDigits) {
  58. $nbDigits = static::randomDigitNotNull();
  59. }
  60. $max = pow(10, $nbDigits) - 1;
  61. if ($max > mt_getrandmax()) {
  62. throw new \InvalidArgumentException('randomNumber() can only generate numbers up to mt_getrandmax()');
  63. }
  64. if ($strict) {
  65. return mt_rand(pow(10, $nbDigits - 1), $max);
  66. }
  67. return mt_rand(0, $max);
  68. }
  69. /**
  70. * Return a random float number
  71. *
  72. * @param int $nbMaxDecimals
  73. * @param int|float $min
  74. * @param int|float $max
  75. * @example 48.8932
  76. *
  77. * @return float
  78. */
  79. public static function randomFloat($nbMaxDecimals = null, $min = 0, $max = null)
  80. {
  81. if (null === $nbMaxDecimals) {
  82. $nbMaxDecimals = static::randomDigit();
  83. }
  84. if (null === $max) {
  85. $max = static::randomNumber();
  86. }
  87. if ($min > $max) {
  88. $tmp = $min;
  89. $min = $max;
  90. $max = $tmp;
  91. }
  92. return round($min + mt_rand() / mt_getrandmax() * ($max - $min), $nbMaxDecimals);
  93. }
  94. /**
  95. * Returns a random number between $min and $max
  96. *
  97. * @param integer $min default to 0
  98. * @param integer $max defaults to 32 bit max integer, ie 2147483647
  99. * @example 79907610
  100. *
  101. * @return integer
  102. */
  103. public static function numberBetween($min = 0, $max = 2147483647)
  104. {
  105. return mt_rand($min, $max);
  106. }
  107. /**
  108. * Returns a random letter from a to z
  109. *
  110. * @return string
  111. */
  112. public static function randomLetter()
  113. {
  114. return chr(mt_rand(97, 122));
  115. }
  116. /**
  117. * Returns a random ASCII character (excluding accents and special chars)
  118. */
  119. public static function randomAscii()
  120. {
  121. return chr(mt_rand(33, 126));
  122. }
  123. /**
  124. * Returns random elements from a provided array
  125. *
  126. * @param array $array Array to take elements from. Defaults to a-f
  127. * @param integer $count Number of elements to take.
  128. * @throws \LengthException When requesting more elements than provided
  129. *
  130. * @return array New array with $count elements from $array
  131. */
  132. public static function randomElements(array $array = array('a', 'b', 'c'), $count = 1)
  133. {
  134. $allKeys = array_keys($array);
  135. $numKeys = count($allKeys);
  136. if ($numKeys < $count) {
  137. throw new \LengthException(sprintf('Cannot get %d elements, only %d in array', $count, $numKeys));
  138. }
  139. $highKey = $numKeys - 1;
  140. $keys = $elements = array();
  141. $numElements = 0;
  142. while ($numElements < $count) {
  143. $num = mt_rand(0, $highKey);
  144. if (isset($keys[$num])) {
  145. continue;
  146. }
  147. $keys[$num] = true;
  148. $elements[] = $array[$allKeys[$num]];
  149. $numElements++;
  150. }
  151. return $elements;
  152. }
  153. /**
  154. * Returns a random element from a passed array
  155. *
  156. * @param array $array
  157. * @return mixed
  158. */
  159. public static function randomElement($array = array('a', 'b', 'c'))
  160. {
  161. if (!$array) {
  162. return null;
  163. }
  164. $elements = static::randomElements($array, 1);
  165. return $elements[0];
  166. }
  167. /**
  168. * Returns a random key from a passed associative array
  169. *
  170. * @param array $array
  171. * @return int|string|null
  172. */
  173. public static function randomKey($array = array())
  174. {
  175. if (!$array) {
  176. return null;
  177. }
  178. $keys = array_keys($array);
  179. $key = $keys[mt_rand(0, count($keys) - 1)];
  180. return $key;
  181. }
  182. /**
  183. * Returns a shuffled version of the argument.
  184. *
  185. * This function accepts either an array, or a string.
  186. *
  187. * @example $faker->shuffle([1, 2, 3]); // [2, 1, 3]
  188. * @example $faker->shuffle('hello, world'); // 'rlo,h eold!lw'
  189. *
  190. * @see shuffleArray()
  191. * @see shuffleString()
  192. *
  193. * @param array|string $arg The set to shuffle
  194. * @return array|string The shuffled set
  195. */
  196. public static function shuffle($arg = '')
  197. {
  198. if (is_array($arg)) {
  199. return static::shuffleArray($arg);
  200. }
  201. if (is_string($arg)) {
  202. return static::shuffleString($arg);
  203. }
  204. throw new \InvalidArgumentException('shuffle() only supports strings or arrays');
  205. }
  206. /**
  207. * Returns a shuffled version of the array.
  208. *
  209. * This function does not mutate the original array. It uses the
  210. * Fisher–Yates algorithm, which is unbiaised, together with a Mersenne
  211. * twister random generator. This function is therefore more random than
  212. * PHP's shuffle() function, and it is seedable.
  213. *
  214. * @link http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
  215. *
  216. * @example $faker->shuffleArray([1, 2, 3]); // [2, 1, 3]
  217. *
  218. * @param array $array The set to shuffle
  219. * @return array The shuffled set
  220. */
  221. public static function shuffleArray($array = array())
  222. {
  223. $shuffledArray = array();
  224. $i = 0;
  225. reset($array);
  226. while (list($key, $value) = each($array)) {
  227. if ($i == 0) {
  228. $j = 0;
  229. } else {
  230. $j = mt_rand(0, $i);
  231. }
  232. if ($j == $i) {
  233. $shuffledArray[]= $value;
  234. } else {
  235. $shuffledArray[]= $shuffledArray[$j];
  236. $shuffledArray[$j] = $value;
  237. }
  238. $i++;
  239. }
  240. return $shuffledArray;
  241. }
  242. /**
  243. * Returns a shuffled version of the string.
  244. *
  245. * This function does not mutate the original string. It uses the
  246. * Fisher–Yates algorithm, which is unbiaised, together with a Mersenne
  247. * twister random generator. This function is therefore more random than
  248. * PHP's shuffle() function, and it is seedable. Additionally, it is
  249. * UTF8 safe if the mb extension is available.
  250. *
  251. * @link http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
  252. *
  253. * @example $faker->shuffleString('hello, world'); // 'rlo,h eold!lw'
  254. *
  255. * @param string $string The set to shuffle
  256. * @param string $encoding The string encoding (defaults to UTF-8)
  257. * @return string The shuffled set
  258. */
  259. public static function shuffleString($string = '', $encoding = 'UTF-8')
  260. {
  261. if (function_exists('mb_strlen')) {
  262. // UTF8-safe str_split()
  263. $array = array();
  264. $strlen = mb_strlen($string, $encoding);
  265. for ($i = 0; $i < $strlen; $i++) {
  266. $array []= mb_substr($string, $i, 1, $encoding);
  267. }
  268. } else {
  269. $array = str_split($string, 1);
  270. }
  271. return join('', static::shuffleArray($array));
  272. }
  273. /**
  274. * Replaces all hash sign ('#') occurrences with a random number
  275. * Replaces all percentage sign ('%') occurrences with a not null number
  276. *
  277. * @param string $string String that needs to bet parsed
  278. * @return string
  279. */
  280. public static function numerify($string = '###')
  281. {
  282. // instead of using randomDigit() several times, which is slow,
  283. // count the number of hashes and generate once a large number
  284. $toReplace = array();
  285. for ($i = 0, $count = strlen($string); $i < $count; $i++) {
  286. if ($string[$i] === '#') {
  287. $toReplace []= $i;
  288. }
  289. }
  290. if ($nbReplacements = count($toReplace)) {
  291. $maxAtOnce = strlen((string) mt_getrandmax()) - 1;
  292. $numbers = '';
  293. $i = 0;
  294. while ($i < $nbReplacements) {
  295. $size = min($nbReplacements - $i, $maxAtOnce);
  296. $numbers .= str_pad(static::randomNumber($size), $size, '0', STR_PAD_LEFT);
  297. $i += $size;
  298. }
  299. for ($i = 0; $i < $nbReplacements; $i++) {
  300. $string[$toReplace[$i]] = $numbers[$i];
  301. }
  302. }
  303. $string = preg_replace_callback('/\%/u', 'static::randomDigitNotNull', $string);
  304. return $string;
  305. }
  306. /**
  307. * Replaces all question mark ('?') occurrences with a random letter
  308. *
  309. * @param string $string String that needs to bet parsed
  310. * @return string
  311. */
  312. public static function lexify($string = '????')
  313. {
  314. return preg_replace_callback('/\?/u', 'static::randomLetter', $string);
  315. }
  316. /**
  317. * Replaces hash signs and question marks with random numbers and letters
  318. *
  319. * @param string $string String that needs to bet parsed
  320. * @return string
  321. */
  322. public static function bothify($string = '## ??')
  323. {
  324. return static::lexify(static::numerify($string));
  325. }
  326. /**
  327. * Replaces * signs with random numbers and letters and special characters
  328. *
  329. * @example $faker->asciify(''********'); // "s5'G!uC3"
  330. *
  331. * @param string $string String that needs to bet parsed
  332. * @return string
  333. */
  334. public static function asciify($string = '****')
  335. {
  336. return preg_replace_callback('/\*/u', 'static::randomAscii', $string);
  337. }
  338. /**
  339. * Transforms a basic regular expression into a random string satisfying the expression.
  340. *
  341. * @example $faker->regexify('[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'); // sm0@y8k96a.ej
  342. *
  343. * Regex delimiters '/.../' and begin/end markers '^...$' are ignored.
  344. *
  345. * Only supports a small subset of the regex syntax. For instance,
  346. * unicode, negated classes, unbouned ranges, subpatterns, back references,
  347. * assertions, recursive patterns, and comments are not supported. Escaping
  348. * support is extremely fragile.
  349. *
  350. * This method is also VERY slow. Use it only when no other formatter
  351. * can generate the fake data you want. For instance, prefer calling
  352. * `$faker->email` rather than `regexify` with the previous regular
  353. * expression.
  354. *
  355. * Also note than `bothify` can probably do most of what this method does,
  356. * but much faster. For instance, for a dummy email generation, try
  357. * `$faker->bothify('?????????@???.???')`.
  358. *
  359. * @see https://github.com/icomefromthenet/ReverseRegex for a more robust implementation
  360. *
  361. * @param string $regex A regular expression (delimiters are optional)
  362. * @return string
  363. */
  364. public static function regexify($regex = '')
  365. {
  366. // ditch the anchors
  367. $regex = preg_replace('/^\/?\^?/', '', $regex);
  368. $regex = preg_replace('/\$?\/?$/', '', $regex);
  369. // All {2} become {2,2}
  370. $regex = preg_replace('/\{(\d+)\}/', '{\1,\1}', $regex);
  371. // Single-letter quantifiers (?, *, +) become bracket quantifiers ({0,1}, {0,rand}, {1, rand})
  372. $regex = preg_replace('/(?<!\\\)\?/', '{0,1}', $regex);
  373. $regex = preg_replace('/(?<!\\\)\*/', '{0,' . static::randomDigitNotNull() . '}', $regex);
  374. $regex = preg_replace('/(?<!\\\)\+/', '{1,' . static::randomDigitNotNull() . '}', $regex);
  375. // [12]{1,2} becomes [12] or [12][12]
  376. $regex = preg_replace_callback('/(\[[^\]]+\])\{(\d+),(\d+)\}/', function ($matches) {
  377. return str_repeat($matches[1], Base::randomElement(range($matches[2], $matches[3])));
  378. }, $regex);
  379. // (12|34){1,2} becomes (12|34) or (12|34)(12|34)
  380. $regex = preg_replace_callback('/(\([^\)]+\))\{(\d+),(\d+)\}/', function ($matches) {
  381. return str_repeat($matches[1], Base::randomElement(range($matches[2], $matches[3])));
  382. }, $regex);
  383. // A{1,2} becomes A or AA or \d{3} becomes \d\d\d
  384. $regex = preg_replace_callback('/(\\\?.)\{(\d+),(\d+)\}/', function ($matches) {
  385. return str_repeat($matches[1], Base::randomElement(range($matches[2], $matches[3])));
  386. }, $regex);
  387. // (this|that) becomes 'this' or 'that'
  388. $regex = preg_replace_callback('/\((.*?)\)/', function ($matches) {
  389. return Base::randomElement(explode('|', str_replace(array('(', ')'), '', $matches[1])));
  390. }, $regex);
  391. // All A-F inside of [] become ABCDEF
  392. $regex = preg_replace_callback('/\[([^\]]+)\]/', function ($matches) {
  393. return '[' . preg_replace_callback('/(\w|\d)\-(\w|\d)/', function ($range) {
  394. return join(range($range[1], $range[2]), '');
  395. }, $matches[1]) . ']';
  396. }, $regex);
  397. // All [ABC] become B (or A or C)
  398. $regex = preg_replace_callback('/\[([^\]]+)\]/', function ($matches) {
  399. return Base::randomElement(str_split($matches[1]));
  400. }, $regex);
  401. // replace \d with number and \w with letter and . with ascii
  402. $regex = preg_replace_callback('/\\\w/', 'static::randomLetter', $regex);
  403. $regex = preg_replace_callback('/\\\d/', 'static::randomDigit', $regex);
  404. $regex = preg_replace_callback('/(?<!\\\)\./', 'static::randomAscii', $regex);
  405. // remove remaining backslashes
  406. $regex = str_replace('\\', '', $regex);
  407. // phew
  408. return $regex;
  409. }
  410. /**
  411. * Converts string to lowercase.
  412. * Uses mb_string extension if available.
  413. *
  414. * @param string $string String that should be converted to lowercase
  415. * @return string
  416. */
  417. public static function toLower($string = '')
  418. {
  419. return extension_loaded('mbstring') ? mb_strtolower($string, 'UTF-8') : strtolower($string);
  420. }
  421. /**
  422. * Converts string to uppercase.
  423. * Uses mb_string extension if available.
  424. *
  425. * @param string $string String that should be converted to uppercase
  426. * @return string
  427. */
  428. public static function toUpper($string = '')
  429. {
  430. return extension_loaded('mbstring') ? mb_strtoupper($string, 'UTF-8') : strtoupper($string);
  431. }
  432. /**
  433. * Chainable method for making any formatter optional.
  434. *
  435. * @param float $weight Set the probability of receiving a null value.
  436. * "0" will always return null, "1" will always return the generator.
  437. * @return Generator|DefaultGenerator
  438. */
  439. public function optional($weight = 0.5, $default = null)
  440. {
  441. if (mt_rand() / mt_getrandmax() <= $weight) {
  442. return $this->generator;
  443. }
  444. return new DefaultGenerator($default);
  445. }
  446. /**
  447. * Chainable method for making any formatter unique.
  448. *
  449. * <code>
  450. * // will never return twice the same value
  451. * $faker->unique()->randomElement(array(1, 2, 3));
  452. * </code>
  453. *
  454. * @param boolean $reset If set to true, resets the list of existing values
  455. * @param integer $maxRetries Maximum number of retries to find a unique value,
  456. * After which an OverflowException is thrown.
  457. * @throws \OverflowException When no unique value can be found by iterating $maxRetries times
  458. *
  459. * @return UniqueGenerator A proxy class returning only non-existing values
  460. */
  461. public function unique($reset = false, $maxRetries = 10000)
  462. {
  463. if ($reset || !$this->unique) {
  464. $this->unique = new UniqueGenerator($this->generator, $maxRetries);
  465. }
  466. return $this->unique;
  467. }
  468. }