-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
29 changed files
with
1,131 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ jobs: | |
- console | ||
- core | ||
- doctrine-extra | ||
- entity-migrator | ||
- fixer | ||
- framework-extra-bundle | ||
- log | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace DoctrineMigrations; | ||
|
||
use Doctrine\DBAL\Schema\Schema; | ||
use Doctrine\Migrations\AbstractMigration; | ||
|
||
/** | ||
* Auto-generated Migration: Please modify to your needs! | ||
*/ | ||
final class Version20231023001449 extends AbstractMigration | ||
{ | ||
public function getDescription(): string | ||
{ | ||
return ''; | ||
} | ||
|
||
public function up(Schema $schema): void | ||
{ | ||
// this up() migration is auto-generated, please modify it to your needs | ||
$this->addSql('CREATE TABLE draw_entity_migrator__migration ( | ||
id INT AUTO_INCREMENT NOT NULL, | ||
name VARCHAR(255) NOT NULL, | ||
state VARCHAR(255) NOT NULL, | ||
UNIQUE INDEX name (name), | ||
PRIMARY KEY(id) | ||
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); | ||
$this->addSql('CREATE TABLE user_migration ( | ||
id BIGINT AUTO_INCREMENT NOT NULL, | ||
entity_id CHAR(36) NOT NULL COMMENT \'(DC2Type:guid)\', | ||
migration_id INT NOT NULL, | ||
state VARCHAR(255) DEFAULT \'new\' NOT NULL, | ||
transition_logs JSON DEFAULT NULL, | ||
created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', | ||
INDEX IDX_C3FC382681257D5D (entity_id), | ||
INDEX IDX_C3FC382679D9816F (migration_id), | ||
PRIMARY KEY(id) | ||
) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); | ||
$this->addSql('ALTER TABLE | ||
user_migration | ||
ADD | ||
CONSTRAINT FK_C3FC382681257D5D FOREIGN KEY (entity_id) REFERENCES draw_acme__user (id) ON DELETE CASCADE'); | ||
$this->addSql('ALTER TABLE | ||
user_migration | ||
ADD | ||
CONSTRAINT FK_C3FC382679D9816F FOREIGN KEY (migration_id) REFERENCES draw_entity_migrator__migration (id) ON DELETE CASCADE'); | ||
} | ||
|
||
public function down(Schema $schema): void | ||
{ | ||
// this down() migration is auto-generated, please modify it to your needs | ||
$this->addSql('ALTER TABLE user_migration DROP FOREIGN KEY FK_C3FC382681257D5D'); | ||
$this->addSql('ALTER TABLE user_migration DROP FOREIGN KEY FK_C3FC382679D9816F'); | ||
$this->addSql('DROP TABLE draw_entity_migrator__migration'); | ||
$this->addSql('DROP TABLE user_migration'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
namespace App\Entity; | ||
|
||
use Doctrine\ORM\Mapping as ORM; | ||
use Draw\Component\EntityMigrator\Entity\BaseEntityMigration; | ||
use Draw\Component\EntityMigrator\MigrationTargetEntityInterface; | ||
|
||
#[ | ||
ORM\Entity, | ||
ORM\Table(name: 'user_migration'), | ||
] | ||
class UserMigration extends BaseEntityMigration | ||
{ | ||
#[ | ||
ORM\ManyToOne(targetEntity: User::class), | ||
ORM\JoinColumn(name: 'entity_id', nullable: false, onDelete: 'CASCADE') | ||
] | ||
protected MigrationTargetEntityInterface $entity; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
<?php | ||
|
||
namespace App\EntityMigration; | ||
|
||
use App\Entity\User; | ||
use Doctrine\ORM\EntityManagerInterface; | ||
use Doctrine\ORM\EntityRepository; | ||
use Doctrine\Persistence\ManagerRegistry; | ||
use Draw\Component\EntityMigrator\MigrationInterface; | ||
use Draw\Component\EntityMigrator\MigrationTargetEntityInterface; | ||
|
||
/** | ||
* @template-implements MigrationInterface<User> | ||
*/ | ||
class UserSetCommentNullMigration implements MigrationInterface | ||
{ | ||
public static function getName(): string | ||
{ | ||
return 'user-set-comment-null'; | ||
} | ||
|
||
public function __construct(private ManagerRegistry $managerRegistry) | ||
{ | ||
|
||
} | ||
|
||
public static function getTargetEntityClass(): string | ||
{ | ||
return User::class; | ||
} | ||
|
||
public function migrate(MigrationTargetEntityInterface $entity): void | ||
{ | ||
$entity->setComment(''); | ||
} | ||
|
||
public function needMigration(MigrationTargetEntityInterface $entity): bool | ||
{ | ||
return '' !== $entity->getComment(); | ||
} | ||
|
||
public function findAllThatNeedMigration(): iterable | ||
{ | ||
$manager = $this->managerRegistry->getManagerForClass(User::class); | ||
\assert($manager instanceof EntityManagerInterface); | ||
|
||
$query = $manager | ||
->createQuery('SELECT user.id FROM '.User::class.' user WHERE user.comment != :comment'); | ||
|
||
foreach ($query->toIterable(['comment' => ''], $query::HYDRATE_SCALAR) as $userId) { | ||
yield $manager->getReference(User::class, $userId['id']); | ||
} | ||
} | ||
|
||
public function countAllThatNeedMigration(): ?int | ||
{ | ||
$manager = $this->managerRegistry->getManagerForClass(User::class); | ||
\assert($manager instanceof EntityManagerInterface); | ||
|
||
return (int) $manager | ||
->createQuery('SELECT count(user) FROM '.User::class.' user WHERE user.comment != :comment') | ||
->setParameter('comment', '') | ||
->getSingleScalarResult(); | ||
} | ||
|
||
public function migrationIsCompleted(): bool | ||
{ | ||
$repository = $this->managerRegistry->getRepository(User::class); | ||
\assert($repository instanceof EntityRepository); | ||
|
||
return null === $repository | ||
->createQueryBuilder('user') | ||
->select('user.id') | ||
->where('user.comment != ""') | ||
->setMaxResults(1) | ||
->getQuery() | ||
->getOneOrNullResult(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/vendor/ | ||
/.idea/ | ||
composer.lock | ||
|
||
###> phpunit/phpunit ### | ||
/phpunit.xml | ||
.phpunit.result.cache | ||
###< phpunit/phpunit ### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
<?php | ||
|
||
namespace Draw\Component\EntityMigrator\Command; | ||
|
||
use Doctrine\Persistence\ManagerRegistry; | ||
use Draw\Component\EntityMigrator\Entity\Migration; | ||
use Draw\Component\EntityMigrator\Migrator; | ||
use Draw\Component\EntityMigrator\Repository\EntityMigrationRepository; | ||
use Symfony\Component\Console\Attribute\AsCommand; | ||
use Symfony\Component\Console\Command\Command; | ||
use Symfony\Component\Console\Input\InputInterface; | ||
use Symfony\Component\Console\Input\InputOption; | ||
use Symfony\Component\Console\Output\OutputInterface; | ||
use Symfony\Component\Console\Question\ChoiceQuestion; | ||
use Symfony\Component\Console\Style\SymfonyStyle; | ||
|
||
#[AsCommand( | ||
name: 'draw:entity-migrator:migrate-all', | ||
description: 'Migrate all entities', | ||
)] | ||
class MigrateAllCommand extends Command | ||
{ | ||
public function __construct( | ||
private Migrator $migrator, | ||
private EntityMigrationRepository $entityMigrationRepository, | ||
private ManagerRegistry $managerRegistry | ||
) { | ||
parent::__construct(); | ||
} | ||
|
||
protected function configure(): void | ||
{ | ||
$this | ||
->addArgument('migration-name', null, 'The migration name to migrate') | ||
->addOption('now', null, InputOption::VALUE_NONE, 'Execute the migration now'); | ||
} | ||
|
||
protected function interact(InputInterface $input, OutputInterface $output): void | ||
{ | ||
$io = new SymfonyStyle($input, $output); | ||
|
||
if (!$input->getArgument('migration-name')) { | ||
$action = $input->getOption('now') ? 'process' : 'queue'; | ||
$io->block( | ||
sprintf( | ||
'Which migration do you want to %s?', | ||
$action | ||
), | ||
null, | ||
'fg=white;bg=blue', | ||
' ', | ||
true | ||
); | ||
|
||
$question = new ChoiceQuestion( | ||
'Select which migration', | ||
array_map( | ||
fn (Migration $migration) => $migration->getName(), | ||
$this->managerRegistry->getRepository(Migration::class)->findAll() | ||
) | ||
); | ||
|
||
$input->setArgument('migration-name', $io->askQuestion($question)); | ||
} | ||
} | ||
|
||
protected function execute(InputInterface $input, OutputInterface $output): int | ||
{ | ||
$io = new SymfonyStyle( | ||
$input, | ||
$output | ||
); | ||
|
||
$now = (bool) $input->getOption('now'); | ||
|
||
$migration = $this->migrator->getMigration($input->getArgument('migration-name')); | ||
|
||
$migrationEntity = $this->managerRegistry | ||
->getRepository(Migration::class) | ||
->findOneBy(['name' => $migration::getName()]); | ||
|
||
$count = $migration->countAllThatNeedMigration(); | ||
|
||
if (0 === $count) { | ||
$io->warning('No entity need migration'); | ||
|
||
return Command::SUCCESS; | ||
} | ||
|
||
$progress = $io->createProgressBar($count ?? 0); | ||
|
||
$realCount = 0; | ||
foreach ($migration->findAllThatNeedMigration() as $entity) { | ||
$entityMigration = $this->entityMigrationRepository->load($entity, $migrationEntity); | ||
|
||
if ($now) { | ||
$this->migrator->migrate($entityMigration); | ||
} else { | ||
$this->migrator->queue($entityMigration); | ||
} | ||
|
||
++$realCount; | ||
$progress->advance(); | ||
} | ||
|
||
$progress->finish(); | ||
|
||
$io->newLine(); | ||
|
||
$io->success(sprintf( | ||
'Migration %s %s for %d entities', | ||
$migration::getName(), | ||
$now ? 'processed' : 'queued', | ||
$realCount | ||
)); | ||
|
||
return Command::SUCCESS; | ||
} | ||
} |
Oops, something went wrong.