Skip to content

Instantly share code, notes, and snippets.

@OussamaMater
Created May 27, 2024 21:40
Show Gist options
  • Save OussamaMater/b5cb099d81529c8feb503ecdd5469183 to your computer and use it in GitHub Desktop.
Save OussamaMater/b5cb099d81529c8feb503ecdd5469183 to your computer and use it in GitHub Desktop.
<?php
namespace App\Support;
use Closure;
use Faker\Generator;
class UniqueAndValidGenerator
{
protected Generator $generator;
protected Closure $validator;
protected int $maxRetries;
protected array $uniques = [];
/**
* @param array<string, array<string, null>> $uniques
*/
public function __construct(Generator $generator, Closure $validator = null, int $maxRetries = 10000, &$uniques = [])
{
if (null === $validator) {
$validator = static function () {
return true;
};
} elseif (!is_callable($validator)) {
throw new \InvalidArgumentException('ValidGenerator only accepts callables as the validator argument');
}
$this->generator = $generator;
$this->validator = $validator;
$this->maxRetries = $maxRetries;
$this->uniques = &$uniques;
}
public function ext(string $id)
{
return new self($this->generator->ext($id), $this->validator, $this->maxRetries, $this->uniques);
}
/**
* Catch and proxy all generator calls but return only unique and valid values
*
* @param string $attribute
*
* @deprecated Use a method instead.
*/
public function __get($attribute)
{
trigger_deprecation('fakerphp/faker', '1.14', 'Accessing property "%s" is deprecated, use "%s()" instead.', $attribute, $attribute);
return $this->__call($attribute, []);
}
/**
* Catch and proxy all generator calls with arguments but return only unique and valid values
*
* @param string $name
* @param array $arguments
*/
public function __call($name, $arguments)
{
if (!isset($this->uniques[$name])) {
$this->uniques[$name] = [];
}
$i = 0;
do {
$res = call_user_func_array([$this->generator, $name], $arguments);
++$i;
if ($i > $this->maxRetries) {
throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a valid and unique value', $this->maxRetries));
}
} while (!call_user_func($this->validator, $res) || array_key_exists(serialize($res), $this->uniques[$name]));
$this->uniques[$name][serialize($res)] = null;
return $res;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment