Skip to content

Commit

Permalink
Fixtures as services + group support
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjantetteroo committed Feb 8, 2019
1 parent 266a52b commit 6696313
Show file tree
Hide file tree
Showing 12 changed files with 390 additions and 36 deletions.
110 changes: 75 additions & 35 deletions Command/LoadDataFixturesDoctrineODMCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Doctrine\Bundle\MongoDBBundle\Command;

use Doctrine\Bundle\MongoDBBundle\Loader\SymfonyFixturesLoaderInterface;
use Doctrine\Bundle\MongoDBBundle\ManagerRegistry;
use Doctrine\Common\DataFixtures\Executor\MongoDBExecutor;
use Doctrine\Common\DataFixtures\Loader;
Expand All @@ -11,6 +12,7 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpKernel\KernelInterface;

/**
Expand All @@ -21,13 +23,22 @@
*/
class LoadDataFixturesDoctrineODMCommand extends DoctrineODMCommand
{
/**
* @var KernelInterface
*/
private $kernel;

public function __construct(ManagerRegistry $registry = null, KernelInterface $kernel = null)
/**
* @var SymfonyFixturesLoaderInterface
*/
private $fixturesLoader;

public function __construct(ManagerRegistry $registry = null, KernelInterface $kernel = null, SymfonyFixturesLoaderInterface $fixturesLoader)
{
parent::__construct($registry);

$this->kernel = $kernel;
$this->fixturesLoader = $fixturesLoader;
}

/**
Expand All @@ -45,32 +56,45 @@ protected function configure()
->setDescription('Load data fixtures to your database.')
->addOption('fixtures', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The directory or file to load data fixtures from.')
->addOption('bundles', 'b', InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'The bundles to load data fixtures from.')
->addOption('services', null, InputOption::VALUE_NONE, 'Use services as fixtures')
->addOption('group', null, InputOption::VALUE_IS_ARRAY|InputOption::VALUE_REQUIRED, 'Only load fixtures that belong to this group (use with --services)')
->addOption('append', null, InputOption::VALUE_NONE, 'Append the data fixtures instead of flushing the database first.')
->addOption('dm', null, InputOption::VALUE_REQUIRED, 'The document manager to use for this command.')
->setHelp(<<<EOT
The <info>doctrine:mongodb:fixtures:load</info> command loads data fixtures from your bundles:
The <info>doctrine:mongodb:fixtures:load</info> command loads data fixtures from your application:
<info>./app/console doctrine:mongodb:fixtures:load</info>
<info>php %command.full_name%</info>
You can also optionally specify the path to fixtures with the <info>--fixtures</info> option:
<info>./app/console doctrine:mongodb:fixtures:load --fixtures=/path/to/fixtures1 --fixtures=/path/to/fixtures2</info>
<info>php %command.full_name%</info> --fixtures=/path/to/fixtures1 --fixtures=/path/to/fixtures2</info>
If you want to append the fixtures instead of flushing the database first you can use the <info>--append</info> option:
<info>./app/console doctrine:mongodb:fixtures:load --append</info>
<info>php %command.full_name%</info> --append</info>
Alternatively, you can also load fixture services instead of files. Fixture services are tagged with `<comment>doctrine.fixture.odm</comment>`.
When using `<comment>--services</comment>`, both `<comment>--fixtures</comment>` and `<comment>--bundles</comment>` will no longer work.
Using `<comment>--services</comment>` will be the default behaviour in 4.0.
When loading fixture services, you can also choose to load only fixtures that live in a certain group:
`<info>php %command.full_name%</info> <comment>--group=group1</comment> <comment>--services</comment>`
EOT
);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
$dm = $this->getManagerRegistry()->getManager($input->getOption('dm'));
$ui = new SymfonyStyle($input, $output);

$dirOrFile = $input->getOption('fixtures');
$bundles = $input->getOption('bundles');
if ($bundles && $dirOrFile) {
throw new \InvalidArgumentException('Use only one option: --bundles or --fixtures.');
$services = (bool) $input->getOption('services');
if (($services && $bundles) || ($services && $dirOrFile) || ($bundles && $dirOrFile)) {
throw new \InvalidArgumentException('Can only use one of "--bundles", "--fixtures", "--services".');
}

if ($input->isInteractive() && !$input->getOption('append')) {
Expand All @@ -82,37 +106,53 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
}

if ($dirOrFile) {
$paths = is_array($dirOrFile) ? $dirOrFile : [$dirOrFile];
} elseif ($bundles) {
$paths = [$this->getKernel()->getRootDir().'/DataFixtures/MongoDB'];
foreach ($bundles as $bundle) {
$paths[] = $this->getKernel()->getBundle($bundle)->getPath();
if (!$services) {
@trigger_error('--bundles and --fixtures are deprecated since version 3.6 and will be removed in 4.0. Use --services instead.', E_USER_DEPRECATED);

if ($dirOrFile) {
$paths = is_array($dirOrFile) ? $dirOrFile : [$dirOrFile];
} elseif ($bundles) {
$paths = [$this->getKernel()->getRootDir().'/DataFixtures/MongoDB'];
foreach ($bundles as $bundle) {
$paths[] = $this->getKernel()->getBundle($bundle)->getPath();
}
} else {
$paths = $this->container->getParameter('doctrine_mongodb.odm.fixtures_dirs');
$paths = is_array($paths) ? $paths : [$paths];
$paths[] = $this->getKernel()->getRootDir().'/DataFixtures/MongoDB';
foreach ($this->getKernel()->getBundles() as $bundle) {
$paths[] = $bundle->getPath().'/DataFixtures/MongoDB';
}
}
} else {
$paths = $this->container->getParameter('doctrine_mongodb.odm.fixtures_dirs');
$paths = is_array($paths) ? $paths : [$paths];
$paths[] = $this->getKernel()->getRootDir().'/DataFixtures/MongoDB';
foreach ($this->getKernel()->getBundles() as $bundle) {
$paths[] = $bundle->getPath().'/DataFixtures/MongoDB';
$loaderClass = $this->container->getParameter('doctrine_mongodb.odm.fixture_loader');
$loader = new $loaderClass($this->container);
foreach ($paths as $path) {
if (is_dir($path)) {
$loader->loadFromDirectory($path);
} else if (is_file($path)) {
$loader->loadFromFile($path);
}
}
}

$loaderClass = $this->container->getParameter('doctrine_mongodb.odm.fixture_loader');
$loader = new $loaderClass($this->container);
foreach ($paths as $path) {
if (is_dir($path)) {
$loader->loadFromDirectory($path);
} else if (is_file($path)) {
$loader->loadFromFile($path);
$fixtures = $loader->getFixtures();
if (!$fixtures) {
throw new \InvalidArgumentException(
sprintf('Could not find any fixtures to load in: %s', "\n\n- ".implode("\n- ", $paths))
);
}
}
} else {
$groups = $input->getOption('group');
$fixtures = $this->fixturesLoader->getFixtures($groups);
if (! $fixtures) {
$message = 'Could not find any fixture services to load';

if (! empty($groups)) {
$message .= sprintf(' in the groups (%s)', implode(', ', $groups));
}

$fixtures = $loader->getFixtures();
if (!$fixtures) {
throw new \InvalidArgumentException(
sprintf('Could not find any fixtures to load in: %s', "\n\n- ".implode("\n- ", $paths))
);
$ui->error($message . '.');

return 1;
}
}

$purger = new MongoDBPurger($dm);
Expand Down
49 changes: 49 additions & 0 deletions DependencyInjection/Compiler/FixturesCompilerPass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/*
* This file is part of the Doctrine Fixtures Bundle
*
* The code was originally distributed inside the Symfony framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
* (c) Doctrine Project
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

final class FixturesCompilerPass implements CompilerPassInterface
{
const FIXTURE_TAG = 'doctrine.fixture.odm';

public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('doctrine_mongodb.odm.symfony.fixtures.loader');
$taggedServices = $container->findTaggedServiceIds(self::FIXTURE_TAG);

$fixtures = [];
foreach ($taggedServices as $serviceId => $tags) {
$groups = [];
foreach ($tags as $tagData) {
if (! isset($tagData['group'])) {
continue;
}

$groups[] = $tagData['group'];
}

$fixtures[] = [
'fixture' => new Reference($serviceId),
'groups' => $groups,
];
}

$definition->addMethodCall('addFixtures', [$fixtures]);
}
}
6 changes: 6 additions & 0 deletions DependencyInjection/DoctrineMongoDBExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

namespace Doctrine\Bundle\MongoDBBundle\DependencyInjection;

use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\FixturesCompilerPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass;
use Doctrine\Bundle\MongoDBBundle\Fixture\ODMFixtureInterface;
use Doctrine\Bundle\MongoDBBundle\Repository\ServiceDocumentRepositoryInterface;
use Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension;
use Symfony\Component\Config\FileLocator;
Expand Down Expand Up @@ -56,6 +58,10 @@ public function load(array $configs, ContainerBuilder $container)
// set the fixtures loader
$container->setParameter('doctrine_mongodb.odm.fixture_loader', $config['fixture_loader']);

// Autowiring fixture loader
$container->registerForAutoconfiguration(ODMFixtureInterface::class)
->addTag(FixturesCompilerPass::FIXTURE_TAG);

// load the connections
$this->loadConnections($config['connections'], $container);

Expand Down
2 changes: 2 additions & 0 deletions DoctrineMongoDBBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

namespace Doctrine\Bundle\MongoDBBundle;

use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\FixturesCompilerPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass;
use Doctrine\Common\Util\ClassUtils;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\CreateHydratorDirectoryPass;
Expand Down Expand Up @@ -33,6 +34,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new CreateHydratorDirectoryPass(), PassConfig::TYPE_BEFORE_REMOVING);
$container->addCompilerPass(new DoctrineValidationPass('mongodb'));
$container->addCompilerPass(new ServiceRepositoryCompilerPass());
$container->addCompilerPass(new FixturesCompilerPass());

if ($container->hasExtension('security')) {
$container->getExtension('security')->addUserProviderFactory(new EntityFactory('mongodb', 'doctrine_mongodb.odm.security.user.provider'));
Expand Down
13 changes: 13 additions & 0 deletions Fixture/Fixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Doctrine\Bundle\MongoDBBundle\Fixture;

use Doctrine\Common\DataFixtures\AbstractFixture;

/**
* Base class designed for data fixtures so they don't have to extend and
* implement different classes/interfaces according to their needs.
*/
abstract class Fixture extends AbstractFixture implements ODMFixtureInterface
{
}
17 changes: 17 additions & 0 deletions Fixture/FixtureGroupInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Doctrine\Bundle\MongoDBBundle\Fixture;

/**
* FixtureGroupInterface can be implemented by fixtures that belong in groups
*/
interface FixtureGroupInterface
{
/**
* This method must return an array of groups
* on which the implementing class belongs to
*
* @return string[]
*/
public static function getGroups();
}
12 changes: 12 additions & 0 deletions Fixture/ODMFixtureInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Doctrine\Bundle\MongoDBBundle\Fixture;

use Doctrine\Common\DataFixtures\FixtureInterface;

/**
* Marks your fixtures that are specifically for the ODM.
*/
interface ODMFixtureInterface extends FixtureInterface
{
}
Loading

0 comments on commit 6696313

Please sign in to comment.