diff --git a/.docs/README.md b/.docs/README.md
index 3676b88..e4f2d37 100755
--- a/.docs/README.md
+++ b/.docs/README.md
@@ -46,22 +46,10 @@ nettrine.fixtures:
Type `bin/console` in your terminal and there should be a `doctrine:fixtures` command group.
-The **doctrine:fixtures:load** command loads data fixtures from your configuration by default:
-
```
bin/console doctrine:fixtures:load
-```
-
-If you want to append the fixtures instead of first flushing the database you can use the **--append** option:
-
-```
bin/console doctrine:fixtures:load --append
-```
-
-By default `Doctrine Fixtures` uses `DELETE` statements to drop the existing rows from
-the database. If you want to use a `TRUNCATE` statement instead, you can use the **--purge-with-truncate** flag:
-
-```
+bin/console doctrine:fixtures:load --fixtures=db/fixtures/development
bin/console doctrine:fixtures:load --purge-with-truncate
```
diff --git a/src/Command/LoadDataFixturesCommand.php b/src/Command/LoadDataFixturesCommand.php
index 901e6b6..f7e4353 100644
--- a/src/Command/LoadDataFixturesCommand.php
+++ b/src/Command/LoadDataFixturesCommand.php
@@ -6,7 +6,9 @@
use Doctrine\Common\DataFixtures\Purger\ORMPurger;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
+use Nettrine\Fixtures\Exceptions\LogicalException;
use Nettrine\Fixtures\Loader\FixturesLoader;
+use Nettrine\Fixtures\Utils\ConsoleHelper;
use Psr\Log\AbstractLogger;
use Stringable;
use Symfony\Component\Console\Attribute\AsCommand;
@@ -38,6 +40,7 @@ protected function configure(): void
$this
->setDescription('Load data fixtures to your database')
->addOption('append', null, InputOption::VALUE_NONE, 'Append the data fixtures instead of deleting all data from the database first.')
+ ->addOption('fixtures', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'File or directory to load data fixtures from.')
->addOption('em', null, InputOption::VALUE_REQUIRED, 'The entity manager to use for this command.')
->addOption('purge-with-truncate', null, InputOption::VALUE_NONE, 'Purge data by using a database-level TRUNCATE statement')
->setHelp(<<<'EOT'
@@ -45,7 +48,9 @@ protected function configure(): void
php %command.full_name%
- Fixtures are services that are tagged with doctrine.fixture.orm.
+ You can also optionally specify the path to fixtures with the --fixtures option:
+
+ %command.name% --fixtures=db/fixtures/development --fixtures=db/fixtures/staging
If you want to append the fixtures instead of flushing the database first you can use the --append option:
@@ -63,25 +68,37 @@ protected function execute(InputInterface $input, OutputInterface $output): int
{
$ui = new SymfonyStyle($input, $output);
- $inputAppend = filter_var($input->getOption('append'), FILTER_VALIDATE_BOOLEAN);
- $inputEm = is_string($input->getOption('em')) && $input->getOption('em') !== '' ? $input->getOption('em') : null;
- $inputTruncate = filter_var($input->getOption('purge-with-truncate'), FILTER_VALIDATE_BOOLEAN);
+ $inputAppend = ConsoleHelper::bool($input->getOption('append'));
+ $inputEm = ConsoleHelper::stringNull($input->getOption('em'));
+ $inputTruncate = ConsoleHelper::bool($input->getOption('purge-with-truncate'));
+ $inputFixtures = ConsoleHelper::arrayString($input->getOption('fixtures'));
$em = $this->managerRegistry->getManager($inputEm);
assert($em instanceof EntityManagerInterface);
+ // Ask user to confirm purging database
if (!$inputAppend) {
if (!$ui->confirm(sprintf('Careful, database "%s" will be purged. Do you want to continue?', $em->getConnection()->getDatabase()), !$input->isInteractive())) {
return 0;
}
}
- $this->fixturesLoader->load();
+ // Load fixtures from given paths
+ if ($inputFixtures === []) {
+ $this->fixturesLoader->load();
+ } else {
+ $this->fixturesLoader->loadPaths($inputFixtures);
+ }
+
$fixtures = $this->fixturesLoader->getFixtures();
if ($fixtures === []) {
- $ui->error('Could not find any fixture services to load.');
+ $paths = $this->fixturesLoader->getPaths();
- return 1;
+ if ($paths === []) {
+ throw new LogicalException('Could not find any fixtures to load.');
+ } else {
+ throw new LogicalException(sprintf('Could not find any fixtures to load in paths: %s', implode(', ', $paths)));
+ }
}
$purger = new ORMPurger($em);
diff --git a/src/DI/FixturesExtension.php b/src/DI/FixturesExtension.php
index dd04d78..4b07937 100644
--- a/src/DI/FixturesExtension.php
+++ b/src/DI/FixturesExtension.php
@@ -3,7 +3,6 @@
namespace Nettrine\Fixtures\DI;
use Nette\DI\CompilerExtension;
-use Nette\DI\Extensions\InjectExtension;
use Nette\Schema\Expect;
use Nette\Schema\Schema;
use Nettrine\Fixtures\Command\LoadDataFixturesCommand;
@@ -33,7 +32,6 @@ public function loadConfiguration(): void
$builder->addDefinition($this->prefix('loadDataFixturesCommand'))
->setFactory(LoadDataFixturesCommand::class)
- ->addTag(InjectExtension::TagInject, true)
->addTag('console.command', 'doctrine:fixtures:load');
}
diff --git a/src/Exceptions/LogicalException.php b/src/Exceptions/LogicalException.php
new file mode 100644
index 0000000..151d39a
--- /dev/null
+++ b/src/Exceptions/LogicalException.php
@@ -0,0 +1,8 @@
+
+ */
+ public static function arrayString(mixed $value): array
+ {
+ if ($value === null || $value === '') {
+ return [];
+ }
+
+ return is_array($value) ? $value : []; // @phpstan-ignore-line
+ }
+
+}
diff --git a/tests/Cases/DI/FixturesExtension.phpt b/tests/Cases/DI/FixturesExtension.phpt
index 4466ae1..544f161 100644
--- a/tests/Cases/DI/FixturesExtension.phpt
+++ b/tests/Cases/DI/FixturesExtension.phpt
@@ -4,20 +4,25 @@ namespace Tests\Cases\Unit\DI;
use Contributte\Tester\Toolkit;
use Contributte\Tester\Utils\ContainerBuilder;
+use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Mockery;
+use Mockery\MockInterface;
use Nette\DI\Compiler;
use Nette\DI\Container;
use Nette\DI\Definitions\Statement;
use Nettrine\Fixtures\Command\LoadDataFixturesCommand;
use Nettrine\Fixtures\DI\FixturesExtension;
+use Nettrine\Fixtures\Exceptions\RuntimeException;
use Nettrine\Fixtures\Loader\FixturesLoader;
+use Symfony\Component\Console\Tester\CommandTester;
use Tester\Assert;
use Tests\Mocks\ContainerFixture;
use Tests\Toolkit\Tests;
require_once __DIR__ . '/../../bootstrap.php';
+// Minimal configuration
Toolkit::test(function (): void {
$container = ContainerBuilder::of()
->withCompiler(function (Compiler $compiler): void {
@@ -57,6 +62,7 @@ Toolkit::test(function (): void {
Assert::type(LoadDataFixturesCommand::class, $command);
});
+// Load by paths
Toolkit::test(function (): void {
$container = ContainerBuilder::of()
->withCompiler(function (Compiler $compiler): void {
@@ -80,3 +86,41 @@ Toolkit::test(function (): void {
$containerFixture = $loader->getFixture(ContainerFixture::class);
Assert::type(Container::class, $containerFixture->getContainer());
});
+
+// Load by paths
+Toolkit::test(function (): void {
+ $container = ContainerBuilder::of()
+ ->withCompiler(function (Compiler $compiler): void {
+ $compiler->getContainerBuilder()
+ ->addDefinition('managerRegistry')
+ ->setType(ManagerRegistry::class)
+ ->setFactory(new Statement(Mockery::class . '::mock', [ManagerRegistry::class]));
+
+ $compiler->addExtension('fixtures', new FixturesExtension());
+ })->build();
+
+ /** @var FixturesLoader $loader */
+ $loader = $container->getByType(FixturesLoader::class);
+ Assert::count(0, $loader->getFixtures());
+
+ $em = Mockery::mock(EntityManagerInterface::class);
+ $em->shouldReceive('getEventManager')->andThrows(new RuntimeException('Not implemented', 999));
+
+ /** @var MockInterface $managerRegistry */
+ $managerRegistry = $container->getByType(ManagerRegistry::class);
+ $managerRegistry->shouldReceive('getManager')->andReturn($em);
+
+ /** @var LoadDataFixturesCommand $loadDataFixtureCommand */
+ $loadDataFixtureCommand = $container->getByType(LoadDataFixturesCommand::class);
+
+ try {
+ $commandTester = new CommandTester($loadDataFixtureCommand);
+ $commandTester->execute([
+ '--append' => true,
+ '--fixtures' => [Tests::FIXTURES_PATH],
+ ]);
+ } catch (RuntimeException $e) {
+ Assert::equal(999, $e->getCode());
+ Assert::count(1, $loader->getFixtures());
+ }
+});