Skip to content

Commit

Permalink
Merge branch '3.6'
Browse files Browse the repository at this point in the history
* 3.6:
  Bring back guards against fixtures with constructor arguments
  Fix wrong namespace for existing test
  Remove types for php 5.6 support
  Copy IntegrationTest from DoctrineFixturesBundle
  Fixtures as services + group support
  Update registration of ResolveTargetDocumentListener
  Fix link to PHP7 usage instructions
  • Loading branch information
alcaeus committed Jun 5, 2019
2 parents a896fcf + c3f9d40 commit 715091d
Show file tree
Hide file tree
Showing 20 changed files with 919 additions and 42 deletions.
113 changes: 77 additions & 36 deletions Command/LoadDataFixturesDoctrineODMCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@

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;
use Doctrine\Common\DataFixtures\Purger\MongoDBPurger;
use InvalidArgumentException;
use RuntimeException;
use Symfony\Component\Console\Input\InputInterface;
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;
use const E_USER_DEPRECATED;
use function class_exists;
use function implode;
use function is_array;
use function is_dir;
use function is_file;
use function sprintf;
use function trigger_error;

/**
* Load data fixtures from bundles.
Expand All @@ -29,11 +33,15 @@ class LoadDataFixturesDoctrineODMCommand extends DoctrineODMCommand
/** @var KernelInterface|null */
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 = null)
{
parent::__construct($registry);

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

/**
Expand All @@ -51,32 +59,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 @@ -88,37 +109,57 @@ 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 doctrine/mongodb-odm-bundle 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';
}
}
$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);
} elseif (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 {
$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';
if (! $this->fixturesLoader) {
throw new RuntimeException('Cannot use fixture services without injecting a fixtures loader.');
}
}

$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);
} elseif (is_file($path)) {
$loader->loadFromFile($path);
}
}
$groups = $input->getOption('group');
$fixtures = $this->fixturesLoader->getFixtures($groups);
if (! $fixtures) {
$message = 'Could not find any fixture services to load';

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

$ui->error($message . '.');

return 1;
}
}

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

declare(strict_types=1);

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
{
public const FIXTURE_TAG = 'doctrine.fixture.odm.mongodb';

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]);
}
}
17 changes: 16 additions & 1 deletion DependencyInjection/DoctrineMongoDBExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

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 Doctrine\Common\EventSubscriber;
use Doctrine\ODM\MongoDB\DocumentManager;
use Symfony\Bridge\Doctrine\DependencyInjection\AbstractDoctrineExtension;
use Symfony\Component\Config\FileLocator;
Expand All @@ -19,6 +22,8 @@
use function array_keys;
use function array_merge;
use function class_exists;
use function class_implements;
use function in_array;
use function reset;
use function sprintf;

Expand Down Expand Up @@ -58,6 +63,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 All @@ -76,7 +85,13 @@ public function load(array $configs, ContainerBuilder $container)
foreach ($config['resolve_target_documents'] as $name => $implementation) {
$def->addMethodCall('addResolveTargetDocument', [$name, $implementation, []]);
}
$def->addTag('doctrine_mongodb.odm.event_listener', ['event' => 'loadClassMetadata']);

// Register service has an event subscriber if implement interface
if (in_array(EventSubscriber::class, class_implements($container->getParameterBag()->resolveValue($def->getClass())))) {
$def->addTag('doctrine_mongodb.odm.event_subscriber');
} else {
$def->addTag('doctrine_mongodb.odm.event_listener', ['event' => 'loadClassMetadata']);
}
}

// BC Aliases for Document Manager
Expand Down
2 changes: 2 additions & 0 deletions DoctrineMongoDBBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\CreateHydratorDirectoryPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\CreateProxyDirectoryPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\FixturesCompilerPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass;
use Doctrine\Bundle\MongoDBBundle\DependencyInjection\DoctrineMongoDBExtension;
use Doctrine\ODM\MongoDB\Configuration;
Expand Down Expand Up @@ -34,6 +35,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')) {
return;
Expand Down
15 changes: 15 additions & 0 deletions Fixture/Fixture.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

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
{
}
19 changes: 19 additions & 0 deletions Fixture/FixtureGroupInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

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();
}
14 changes: 14 additions & 0 deletions Fixture/ODMFixtureInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

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 715091d

Please sign in to comment.