Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/Container/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Xefi\Faker\Container;

use Closure;
use Random\Engine;
use Xefi\Faker\Container\Traits\HasExtensions;
use Xefi\Faker\Container\Traits\HasLocale;
use Xefi\Faker\Container\Traits\HasModifiers;
Expand Down Expand Up @@ -47,13 +48,20 @@ class Container
*/
protected static string $containerMixinManifestPath = './faker_mixin.php';

/**
* @var Engine|null
*/
private ?Engine $engine;

/**
* Create the container instance.
*
* @return void
*/
public function __construct(bool $shouldBuildContainerMixin = true)
public function __construct(?Engine $engine = null, bool $shouldBuildContainerMixin = true)
{
$this->engine = $engine;

Comment thread
coderabbitai[bot] marked this conversation as resolved.
if (!$this->areExtensionsInitialized()) {
$this->registerConfiguredProviders();

Expand Down Expand Up @@ -101,6 +109,14 @@ public static function basePath(string $basePath)
static::$basePath = $basePath;
}

/**
* @return Engine|null
*/
public function getEngine(): ?Engine
{
return $this->engine;
}

/**
* Build container mixin manifest.
*/
Expand Down
13 changes: 8 additions & 5 deletions src/Container/Traits/HasExtensions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Xefi\Faker\Container\Traits;

use Random\Engine;
use Random\Randomizer;
use Xefi\Faker\Container\Container;
use Xefi\Faker\Container\Enum\Locales;
Expand All @@ -27,14 +28,15 @@ trait HasExtensions
/**
* Resolve an array of extensions through the container.
*
* @param array $extensions
* @param array $extensions
* @param Engine|null $engine
*
* @return $this
*/
public function resolveExtensions(array $extensions): self
public function resolveExtensions(array $extensions, ?Engine $engine = null): self
{
foreach ($extensions as $extension) {
$this->resolve($extension);
$this->resolve($extension, $engine);
}

return $this;
Expand All @@ -44,12 +46,13 @@ public function resolveExtensions(array $extensions): self
* Add an extension, resolving through the application.
*
* @param Extension|string $extension
* @param Engine|null $engine
*
* @return Container
*/
protected function resolve(\Xefi\Faker\Extensions\Extension|string $extension): Container
protected function resolve(\Xefi\Faker\Extensions\Extension|string $extension, ?Engine $engine = null): Container
{
$instance = $extension instanceof Extension ? $extension : new $extension(new Randomizer());
$instance = $extension instanceof Extension ? $extension : new $extension(new Randomizer($engine));

// If the extension supports locale variations
if (method_exists($instance, 'getLocale')) {
Expand Down
2 changes: 1 addition & 1 deletion src/Container/Traits/HasModifiers.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ trait HasModifiers
*/
public function nullable(int $weight = 50): self
{
$this->modifiers[] = new NullableModifier(new Randomizer(), $weight);
$this->modifiers[] = new NullableModifier(new Randomizer($this->engine), $weight);

return $this;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Extensions/Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Extension
{
protected Randomizer $randomizer;

public function __construct(Randomizer $randomizer)
final public function __construct(Randomizer $randomizer)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this creates a BC break, given that HasExtenisons trait allows to pass extensions instances, this seems needed, but that would prevent any service injection. What if we want an extension that uses a shared clock for example?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discussed this point with coderabbitai. The current implementation is doing new $extension(new Randomizer()) calls. So the contract have to be fixed in order to work reliably. That being said, with a fresh redesign of that part we could move toward custom constructors.

@martinsoenen martinsoenen Jul 26, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand why you did this, but it can breaks some extensions if someone modified the constructor. I need to talk about this with @GautierDele too

{
$this->randomizer = $randomizer;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Expand Down
13 changes: 11 additions & 2 deletions src/Faker.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Xefi\Faker;

use Random\Engine;
use Xefi\Faker\Container\Container;

/**
Expand All @@ -16,14 +17,22 @@ class Faker
*/
protected ?string $locale;

public function __construct(?string $locale = null)
/**
* The current Randomizer engine.
*
* @var Engine|null
*/
protected ?Engine $engine;

public function __construct(?string $locale = null, ?Engine $engine = null)
{
$this->locale = $locale;
$this->engine = $engine;
}

public function __call(string $method, array $parameters)
{
// We simply redirect calls to container to create a new container for each faker call
return (new Container())->locale($this->locale)->{$method}(...$parameters);
return (new Container($this->engine))->locale($this->locale)->{$method}(...$parameters);
}
}
2 changes: 1 addition & 1 deletion src/Providers/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Provider
public function extensions(array $extensions)
{
Container::starting(function (Container $container) use ($extensions) {
$container->resolveExtensions($extensions);
$container->resolveExtensions($extensions, $container->getEngine());
});
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Support/Extensions/NumberTestExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ public function returnOne()

public function returnNumberBetween($min, $max)
{
return rand($min, $max);
return $this->randomizer->getInt($min, $max);
}
}
32 changes: 32 additions & 0 deletions tests/Unit/Extensions/HashExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,56 @@ public function testSha1(): void
$this->assertMatchesRegularExpression('/^[a-z0-9]{40}$/', $result);
}

public function testSha1IsSeedable(): void
{
$this->assertEquals(
$this->createFresh()->sha1(),
$this->createFresh()->sha1(),
);
}

public function testSha256(): void
{
$result = $this->faker->sha256();

$this->assertMatchesRegularExpression('/^[a-z0-9]{64}$/', $result);
}

public function testSha256IsSeedable(): void
{
$this->assertEquals(
$this->createFresh()->sha256(),
$this->createFresh()->sha256(),
);
}

public function testSha512(): void
{
$result = $this->faker->sha512();

$this->assertMatchesRegularExpression('/^[a-z0-9]{128}$/', $result);
}

public function testSha512IsSeedable(): void
{
$this->assertEquals(
$this->createFresh()->sha512(),
$this->createFresh()->sha512(),
);
}

public function testMd5(): void
{
$result = $this->faker->md5();

$this->assertMatchesRegularExpression('/^[a-fA-F0-9]{32}$/', $result);
}

public function testMd5IsSeedable(): void
{
$this->assertEquals(
$this->createFresh()->md5(),
$this->createFresh()->md5(),
);
}
}
16 changes: 8 additions & 8 deletions tests/Unit/Extensions/InternetExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ protected function setUp(): void

public function testSdl(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

$results = [];

Expand All @@ -34,7 +34,7 @@ public function testSdl(): void

public function testTld(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

$results = [];

Expand All @@ -47,7 +47,7 @@ public function testTld(): void

public function testDomain(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

$results = [];

Expand All @@ -62,7 +62,7 @@ public function testDomain(): void

public function testIp(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

for ($i = 0; $i < 50; $i++) {
$result = $faker->ip();
Expand All @@ -73,7 +73,7 @@ public function testIp(): void

public function testIpv4(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

$results = [];

Expand All @@ -88,7 +88,7 @@ public function testIpv4(): void

public function testIpv6(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

$results = [];

Expand All @@ -103,7 +103,7 @@ public function testIpv6(): void

public function testMacAddress(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

$results = [];

Expand All @@ -118,7 +118,7 @@ public function testMacAddress(): void

public function testEmail(): void
{
$faker = new Container(false);
$faker = new Container(null, false);

$results = [];

Expand Down
15 changes: 14 additions & 1 deletion tests/Unit/Extensions/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Xefi\Faker\Tests\Unit\Extensions;

use Random\Engine\Mt19937;
use Xefi\Faker\Container\Container;
use Xefi\Faker\FakerServiceProvider;

Expand All @@ -15,6 +16,18 @@ protected function setUp(): void

(new FakerServiceProvider())->boot();

$this->faker = new Container(false);
$this->faker = new Container(new Mt19937(19937), false);
}

protected function createFresh(): Container
{
$this->faker->forgetBootstrappers();
$this->faker->forgetExtensions();
$this->faker->forgetModifiers();
$this->faker->forgetStrategies();

(new FakerServiceProvider())->boot();

return new Container(new Mt19937(19937), false);
}
}