LoadDataFixturesDoctrineCommand.php 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?php
  2. declare(strict_types=1);
  3. namespace Doctrine\Bundle\FixturesBundle\Command;
  4. use Doctrine\Bundle\DoctrineBundle\Command\DoctrineCommand;
  5. use Doctrine\Bundle\FixturesBundle\DependencyInjection\CompilerPass\PurgerFactoryCompilerPass;
  6. use Doctrine\Bundle\FixturesBundle\Loader\SymfonyFixturesLoader;
  7. use Doctrine\Bundle\FixturesBundle\Purger\ORMPurgerFactory;
  8. use Doctrine\Bundle\FixturesBundle\Purger\PurgerFactory;
  9. use Doctrine\Common\DataFixtures\Executor\ORMExecutor;
  10. use Doctrine\DBAL\Sharding\PoolingShardConnection;
  11. use Doctrine\Persistence\ManagerRegistry;
  12. use LogicException;
  13. use Symfony\Component\Console\Input\InputInterface;
  14. use Symfony\Component\Console\Input\InputOption;
  15. use Symfony\Component\Console\Output\OutputInterface;
  16. use Symfony\Component\Console\Style\SymfonyStyle;
  17. use const E_USER_DEPRECATED;
  18. use function implode;
  19. use function sprintf;
  20. use function trigger_error;
  21. /**
  22. * Load data fixtures from bundles.
  23. */
  24. class LoadDataFixturesDoctrineCommand extends DoctrineCommand
  25. {
  26. /** @var SymfonyFixturesLoader */
  27. private $fixturesLoader;
  28. /** @var PurgerFactory[] */
  29. private $purgerFactories;
  30. /**
  31. * @param PurgerFactory[] $purgerFactories
  32. */
  33. public function __construct(SymfonyFixturesLoader $fixturesLoader, ?ManagerRegistry $doctrine = null, array $purgerFactories = [])
  34. {
  35. if ($doctrine === null) {
  36. @trigger_error(sprintf(
  37. 'Argument 2 of %s() expects an instance of %s, not passing it will throw a \TypeError in DoctrineFixturesBundle 4.0.',
  38. __METHOD__,
  39. ManagerRegistry::class
  40. ), E_USER_DEPRECATED);
  41. }
  42. parent::__construct($doctrine);
  43. $this->fixturesLoader = $fixturesLoader;
  44. $this->purgerFactories = $purgerFactories;
  45. }
  46. // phpcs:ignore SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint
  47. protected function configure()
  48. {
  49. $this
  50. ->setName('doctrine:fixtures:load')
  51. ->setDescription('Load data fixtures to your database')
  52. ->addOption('append', null, InputOption::VALUE_NONE, 'Append the data fixtures instead of deleting all data from the database first.')
  53. ->addOption('group', null, InputOption::VALUE_IS_ARRAY|InputOption::VALUE_REQUIRED, 'Only load fixtures that belong to this group')
  54. ->addOption('em', null, InputOption::VALUE_REQUIRED, 'The entity manager to use for this command.')
  55. ->addOption('purger', null, InputOption::VALUE_REQUIRED, 'The purger to use for this command', 'default')
  56. ->addOption('purge-exclusions', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'List of database tables to ignore while purging')
  57. ->addOption('shard', null, InputOption::VALUE_REQUIRED, 'The shard connection to use for this command.')
  58. ->addOption('purge-with-truncate', null, InputOption::VALUE_NONE, 'Purge data by using a database-level TRUNCATE statement')
  59. ->setHelp(<<<EOT
  60. The <info>%command.name%</info> command loads data fixtures from your application:
  61. <info>php %command.full_name%</info>
  62. Fixtures are services that are tagged with <comment>doctrine.fixture.orm</comment>.
  63. If you want to append the fixtures instead of flushing the database first you can use the <comment>--append</comment> option:
  64. <info>php %command.full_name%</info> <comment>--append</comment>
  65. By default Doctrine Data Fixtures uses DELETE statements to drop the existing rows from the database.
  66. If you want to use a TRUNCATE statement instead you can use the <comment>--purge-with-truncate</comment> flag:
  67. <info>php %command.full_name%</info> <comment>--purge-with-truncate</comment>
  68. To execute only fixtures that live in a certain group, use:
  69. <info>php %command.full_name%</info> <comment>--group=group1</comment>
  70. EOT
  71. );
  72. }
  73. /**
  74. * @return int
  75. */
  76. // phpcs:ignore SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingReturnTypeHint
  77. protected function execute(InputInterface $input, OutputInterface $output)
  78. {
  79. $ui = new SymfonyStyle($input, $output);
  80. $em = $this->getDoctrine()->getManager($input->getOption('em'));
  81. if (! $input->getOption('append')) {
  82. if (! $ui->confirm(sprintf('Careful, database "%s" will be purged. Do you want to continue?', $em->getConnection()->getDatabase()), ! $input->isInteractive())) {
  83. return 0;
  84. }
  85. }
  86. if ($input->getOption('shard')) {
  87. if (! $em->getConnection() instanceof PoolingShardConnection) {
  88. throw new LogicException(sprintf(
  89. 'Connection of EntityManager "%s" must implement shards configuration.',
  90. $input->getOption('em')
  91. ));
  92. }
  93. $em->getConnection()->connect($input->getOption('shard'));
  94. }
  95. $groups = $input->getOption('group');
  96. $fixtures = $this->fixturesLoader->getFixtures($groups);
  97. if (! $fixtures) {
  98. $message = 'Could not find any fixture services to load';
  99. if (! empty($groups)) {
  100. $message .= sprintf(' in the groups (%s)', implode(', ', $groups));
  101. }
  102. $ui->error($message . '.');
  103. return 1;
  104. }
  105. if (! isset($this->purgerFactories[$input->getOption('purger')])) {
  106. $ui->warning(sprintf(
  107. 'Could not find purger factory with alias "%1$s", using default purger. Did you forget to register the %2$s implementation with tag "%3$s" and alias "%1$s"?',
  108. $input->getOption('purger'),
  109. PurgerFactory::class,
  110. PurgerFactoryCompilerPass::PURGER_FACTORY_TAG
  111. ));
  112. $factory = new ORMPurgerFactory();
  113. } else {
  114. $factory = $this->purgerFactories[$input->getOption('purger')];
  115. }
  116. $purger = $factory->createForEntityManager(
  117. $input->getOption('em'),
  118. $em,
  119. $input->getOption('purge-exclusions'),
  120. $input->getOption('purge-with-truncate')
  121. );
  122. $executor = new ORMExecutor($em, $purger);
  123. $executor->setLogger(static function ($message) use ($ui) : void {
  124. $ui->text(sprintf(' <comment>></comment> <info>%s</info>', $message));
  125. });
  126. $executor->execute($fixtures, $input->getOption('append'));
  127. return 0;
  128. }
  129. }