Skip to content

Commit

Permalink
Refactor FixtureFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
jdreesen committed Mar 16, 2024
1 parent 6e88b18 commit 646e81f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 24 deletions.
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ parameters:
count: 3
path: src/Factory/FixtureFactory.php

-
message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#"
count: 1
path: src/Factory/FixtureFactory.php

-
message: "#^Cannot call method getName\\(\\) on ReflectionClass\\|null\\.$#"
count: 1
Expand Down
52 changes: 33 additions & 19 deletions src/Factory/FixtureFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

class FixtureFactory
{
/** @var array<class-string, Fixture> */
/** @var array<class-string<Fixture>, Fixture> */
private array $instances = [];
/** @var array<class-string, float> */
private array $executionTimes = [];
Expand Down Expand Up @@ -61,11 +61,15 @@ public function createFixtures(array $fixtures): void
if ($this->trackExecutionTime) {
$start = microtime(true);
}
$this->createFixture($this->fixtureMapping[$fixtureNameOrClass] ?? $fixtureNameOrClass, 0);

$this->ensureIsFixture($fixtureClass = $this->fixtureMapping[$fixtureNameOrClass] ?? $fixtureNameOrClass);
$this->createFixture($fixtureClass, 0);

if ($this->trackExecutionTime) {
$this->executionTimes[$fixtureNameOrClass] = microtime(true) - $start;
}
}

if ($this->trackExecutionTime) {
$this->executionTimes['All together'] = array_sum($this->executionTimes);
}
Expand All @@ -75,16 +79,11 @@ public function createFixtures(array $fixtures): void
Cache::enable();
}

/**
* @param class-string<Fixture> $fixtureClass
*/
private function createFixture(string $fixtureClass, int $level): void
{
if (!is_a($fixtureClass, Fixture::class, true)) {
throw new \InvalidArgumentException(sprintf(
'Expected "%s" to implement "%s", but it does not.',
$fixtureClass,
Fixture::class,
));
}

if ($this->trackExecutionTime) {
$this->executionTree[] = ['fixtureClass' => $fixtureClass, 'level' => $level];
}
Expand All @@ -96,9 +95,9 @@ private function createFixture(string $fixtureClass, int $level): void
$this->instances[$fixtureClass] = $this->instantiateFixture($fixtureClass);

$args = [];
foreach ($this->iterateMethodParameterTypeNames($fixtureClass, 'create') as $type) {
$this->createFixture($type, $level + 1);
$args[] = $this->instances[$type];
foreach ($this->getDependencies($fixtureClass, 'create') as $dependentFixtureClass) {
$this->createFixture($dependentFixtureClass, $level + 1);
$args[] = $this->instances[$dependentFixtureClass];
}

$this->instances[$fixtureClass]->create(...$args);
Expand All @@ -113,28 +112,43 @@ private function instantiateFixture(string $fixtureClass): Fixture
}

throw new \RuntimeException(sprintf(
'No instantiator found that is is able to instantiate fixtures of type "%s".',
'No instantiator found that is able to instantiate fixtures of type "%s".',
$fixtureClass,
));
}

/**
* @return list<class-string>
* @return list<class-string<Fixture>>
*/
private function iterateMethodParameterTypeNames(string $fixtureClass, string $methodName): iterable
private function getDependencies(string $fixtureClass, string $methodName): iterable
{
foreach ((new \ReflectionMethod($fixtureClass, $methodName))->getParameters() as $parameter) {
if (!$type = $parameter->getType()) {
$type = $parameter->getType();

if (!$type instanceof \ReflectionNamedType) {
throw new \LogicException(sprintf(
'Parameter "$%s" of %s::%s() has no type, while it should be an implementation of "%s".',
'Parameter "$%s" of %s::%s() has an invalid type.',
$parameter->getName(),
$parameter->getDeclaringClass()->getName(),
$parameter->getDeclaringFunction()->getName(),
Fixture::class,
));
}

$this->ensureIsFixture($type->getName());

yield $type->getName();
}
}

/** @phpstan-assert class-string<Fixture> $fixtureClass */
private function ensureIsFixture(string $fixtureClass): void
{
if (!is_a($fixtureClass, Fixture::class, true)) {
throw new \InvalidArgumentException(sprintf(
'Expected "%s" to implement "%s", but it does not.',
$fixtureClass,
Fixture::class,
));
}
}
}

0 comments on commit 646e81f

Please sign in to comment.