Skip to content

Commit b7f5ed4

Browse files
authored
Merge pull request #421 from cs278/load-dependencies
Automatically extract fixture dependencies
2 parents 838207b + 8b3d927 commit b7f5ed4

File tree

5 files changed

+82
-31
lines changed

5 files changed

+82
-31
lines changed

phpstan-baseline.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ parameters:
44
- tests/IntegrationTest.php
55

66
ignoreErrors:
7+
-
8+
message: "#^Call to an undefined method Doctrine\\\\Bundle\\\\FixturesBundle\\\\Loader\\\\SymfonyFixturesLoader\\:\\:getFixture\\(\\)\\.$#"
9+
count: 1
10+
path: src/Loader/SymfonyFixturesLoader.php
11+
712
-
813
message: "#^Call to an undefined static method Doctrine\\\\Bundle\\\\FixturesBundle\\\\Loader\\\\SymfonyBridgeLoader\\:\\:addFixture\\(\\)\\.$#"
914
count: 1

src/Loader/SymfonyFixturesLoader.php

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,8 @@
1010
use Doctrine\Common\DataFixtures\FixtureInterface;
1111
use LogicException;
1212
use ReflectionClass;
13-
use RuntimeException;
1413

15-
use function array_key_exists;
14+
use function array_keys;
1615
use function array_values;
1716
use function get_class;
1817
use function sprintf;
@@ -99,19 +98,22 @@ public function getFixtures(array $groups = []): array
9998
return $fixtures;
10099
}
101100

102-
$filteredFixtures = [];
103-
foreach ($fixtures as $fixture) {
104-
foreach ($groups as $group) {
105-
$fixtureClass = get_class($fixture);
106-
if (isset($this->groupsFixtureMapping[$group][$fixtureClass])) {
107-
$filteredFixtures[$fixtureClass] = $fixture;
108-
continue 2;
109-
}
101+
$requiredFixtures = [];
102+
foreach ($groups as $group) {
103+
if (! isset($this->groupsFixtureMapping[$group])) {
104+
continue;
110105
}
106+
107+
$requiredFixtures += $this->collectDependencies(...array_keys($this->groupsFixtureMapping[$group]));
111108
}
112109

113-
foreach ($filteredFixtures as $fixture) {
114-
$this->validateDependencies($filteredFixtures, $fixture);
110+
$filteredFixtures = [];
111+
foreach ($fixtures as $order => $fixture) {
112+
$fixtureClass = get_class($fixture);
113+
if (isset($requiredFixtures[$fixtureClass])) {
114+
$filteredFixtures[$order] = $fixture;
115+
continue;
116+
}
115117
}
116118

117119
return array_values($filteredFixtures);
@@ -130,22 +132,25 @@ private function addGroupsFixtureMapping(string $className, array $groups): void
130132
}
131133

132134
/**
133-
* @param string[] $fixtures An array of fixtures with class names as keys
135+
* Collect any dependent fixtures from the given classes.
134136
*
135-
* @throws RuntimeException
137+
* @psalm-return array<string,true>
136138
*/
137-
private function validateDependencies(array $fixtures, FixtureInterface $fixture): void
139+
private function collectDependencies(string ...$fixtureClass): array
138140
{
139-
if (! $fixture instanceof DependentFixtureInterface) {
140-
return;
141-
}
141+
$dependencies = [];
142142

143-
$dependenciesClasses = $fixture->getDependencies();
143+
foreach ($fixtureClass as $class) {
144+
$dependencies[$class] = true;
145+
$fixture = $this->getFixture($class);
144146

145-
foreach ($dependenciesClasses as $class) {
146-
if (! array_key_exists($class, $fixtures)) {
147-
throw new RuntimeException(sprintf('Fixture "%s" was declared as a dependency for fixture "%s", but it was not included in any of the loaded fixture groups.', $class, get_class($fixture)));
147+
if (! $fixture instanceof DependentFixtureInterface) {
148+
continue;
148149
}
150+
151+
$dependencies += $this->collectDependencies(...$fixture->getDependencies());
149152
}
153+
154+
return $dependencies;
150155
}
151156
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures;
6+
7+
use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;
8+
use Doctrine\Bundle\FixturesBundle\ORMFixtureInterface;
9+
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
10+
use Doctrine\Persistence\ObjectManager;
11+
12+
class WithDeepDependenciesFixtures implements ORMFixtureInterface, DependentFixtureInterface, FixtureGroupInterface
13+
{
14+
public function load(ObjectManager $manager): void
15+
{
16+
// ...
17+
}
18+
19+
/**
20+
* {@inheritDoc}
21+
*/
22+
public function getDependencies(): array
23+
{
24+
return [WithDependenciesFixtures::class, DependentOnRequiredConstructorArgsFixtures::class];
25+
}
26+
27+
/**
28+
* {@inheritDoc}
29+
*/
30+
public static function getGroups(): array
31+
{
32+
return ['groupWithDeepDependencies'];
33+
}
34+
}

tests/Fixtures/FooBundle/DataFixtures/WithDependenciesFixtures.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ public function getDependencies(): array
2929
*/
3030
public static function getGroups(): array
3131
{
32-
return ['missingDependencyGroup', 'fulfilledDependencyGroup'];
32+
return ['groupWithDependencies', 'fulfilledDependencyGroup'];
3333
}
3434
}

tests/IntegrationTest.php

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use Doctrine\Bundle\FixturesBundle\Purger\PurgerFactory;
1212
use Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\DependentOnRequiredConstructorArgsFixtures;
1313
use Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\OtherFixtures;
14+
use Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\RequiredConstructorArgsFixtures;
15+
use Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\WithDeepDependenciesFixtures;
1416
use Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\WithDependenciesFixtures;
1517
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
1618
use Doctrine\Common\EventManager;
@@ -19,7 +21,6 @@
1921
use Doctrine\Persistence\ManagerRegistry;
2022
use LogicException;
2123
use PHPUnit\Framework\TestCase;
22-
use RuntimeException;
2324
use Symfony\Component\Console\Tester\CommandTester;
2425
use Symfony\Component\DependencyInjection\Alias;
2526
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -173,18 +174,26 @@ public function testFixturesLoaderWithGroupsOptionViaTag(): void
173174
$this->assertCount(0, $loader->getFixtures(['group3']));
174175
}
175176

176-
public function testLoadFixturesViaGroupWithMissingDependency(): void
177+
public function testLoadFixturesViaGroupWithDependenciesNotInGroup(): void
177178
{
178179
$kernel = new IntegrationTestKernel('dev', true);
179180
$kernel->addServices(static function (ContainerBuilder $c): void {
180-
// has a "staging" group via the getGroups() method
181181
$c->autowire(OtherFixtures::class)
182182
->addTag(FixturesCompilerPass::FIXTURE_TAG);
183183

184-
// no getGroups() method
185184
$c->autowire(WithDependenciesFixtures::class)
186185
->addTag(FixturesCompilerPass::FIXTURE_TAG);
187186

187+
$c->autowire(WithDeepDependenciesFixtures::class)
188+
->addTag(FixturesCompilerPass::FIXTURE_TAG);
189+
190+
$c->autowire(RequiredConstructorArgsFixtures::class)
191+
->setArgument('$fooRequiredArg', 'test')
192+
->addTag(FixturesCompilerPass::FIXTURE_TAG);
193+
194+
$c->autowire(DependentOnRequiredConstructorArgsFixtures::class)
195+
->addTag(FixturesCompilerPass::FIXTURE_TAG);
196+
188197
$c->setAlias('test.doctrine.fixtures.loader', new Alias('doctrine.fixtures.loader', true));
189198
});
190199
$kernel->boot();
@@ -193,10 +202,8 @@ public function testLoadFixturesViaGroupWithMissingDependency(): void
193202
$loader = $container->get('test.doctrine.fixtures.loader');
194203
$this->assertInstanceOf(SymfonyFixturesLoader::class, $loader);
195204

196-
$this->expectException(RuntimeException::class);
197-
$this->expectExceptionMessage('Fixture "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\OtherFixtures" was declared as a dependency for fixture "Doctrine\Bundle\FixturesBundle\Tests\Fixtures\FooBundle\DataFixtures\WithDependenciesFixtures", but it was not included in any of the loaded fixture groups.');
198-
199-
$loader->getFixtures(['missingDependencyGroup']);
205+
self::assertCount(2, $loader->getFixtures(['groupWithDependencies']));
206+
self::assertCount(5, $loader->getFixtures(['groupWithDeepDependencies']));
200207
}
201208

202209
public function testLoadFixturesViaGroupWithFulfilledDependency(): void

0 commit comments

Comments
 (0)