Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/Phinx/Console/Command/Migrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,17 @@ protected function configure(): void
$this->setDescription('Migrate the database')
->addOption('--target', '-t', InputOption::VALUE_REQUIRED, 'The version number to migrate to')
->addOption('--date', '-d', InputOption::VALUE_REQUIRED, 'The date to migrate to')
->addOption('--count', '-k', InputOption::VALUE_REQUIRED, 'The number of migrations to run')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldnt -n be better here than k?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-n is taken up by builtin option that comes from symfony console:

 -n, --no-interaction  Do not ask any interactive question

->addOption('--dry-run', '-x', InputOption::VALUE_NONE, 'Dump query to standard output instead of executing it')
->addOption('--fake', null, InputOption::VALUE_NONE, "Mark any migrations selected as run, but don't actually execute them")
->setHelp(
<<<EOT
The <info>migrate</info> command runs all available migrations, optionally up to a specific version
The <info>migrate</info> command runs all available migrations, optionally up to a specific version, date, or count.

<info>phinx migrate -e development</info>
<info>phinx migrate -e development -t 20110103081132</info>
<info>phinx migrate -e development -d 20110103</info>
<info>phinx migrate -e development -k 5</info>
<info>phinx migrate -e development -v</info>

EOT,
Expand All @@ -68,6 +70,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
/** @var string|null $environment */
$environment = $input->getOption('environment');
$date = $input->getOption('date');
$count = $input->getOption('count') !== null ? (int)$input->getOption('count') : null;
$fake = (bool)$input->getOption('fake');

$success = $this->writeInformationOutput($environment, $output);
Expand All @@ -85,7 +88,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
try {
// run the migrations
$start = microtime(true);
if ($date !== null) {
if ($count !== null) {
$this->getManager()->migrateToCount($environment, $count, $fake);
} elseif ($date !== null) {
$this->getManager()->migrateToDateTime($environment, new DateTime($date), $fake);
} else {
$this->getManager()->migrate($environment, $version, $fake);
Expand Down
24 changes: 24 additions & 0 deletions src/Phinx/Migration/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,30 @@ public function migrateToDateTime(string $environment, DateTime $dateTime, bool
}
}

/**
* Migrate an environment to a specific number of migrations.
*
* @param string $environment Environment
* @param int $count Number of migrations to apply
* @param bool $fake flag that if true, we just record running the migration, but not actually do the migration
* @return void
*/
public function migrateToCount(string $environment, int $count, bool $fake = false): void
{
$versions = array_keys($this->getMigrations($environment));
$env = $this->getEnvironment($environment);
$current = $env->getCurrentVersion();

if ($current === 0) {
$version = $versions[$count - 1];
} else {
$currentIdx = array_search($current, $versions, true);
$version = $versions[min($currentIdx + $count, count($versions) - 1)];
}

$this->migrate($environment, $version, $fake);
}

/**
* Migrate an environment to the specified version.
*
Expand Down
32 changes: 32 additions & 0 deletions tests/Phinx/Console/Command/MigrateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,38 @@ public function testExecuteWithDate(): void
$this->assertSame(AbstractCommand::CODE_SUCCESS, $exitCode);
}

public function testExecuteWithCount(): void
{
$application = new PhinxApplication();
$application->add(new Migrate());

/** @var Migrate $command */
$command = $application->find('migrate');

// mock the manager class
/** @var Manager&MockObject $managerStub */
$managerStub = $this->getMockBuilder(Manager::class)
->setConstructorArgs([$this->config, $this->input, $this->output])
->getMock();
$managerStub->expects($this->never())
->method('migrate');
$managerStub->expects($this->once())
->method('migrateToCount')
->with('development', 5, false);

$command->setConfig($this->config);
$command->setManager($managerStub);

$commandTester = new CommandTester($command);
$exitCode = $commandTester->execute(
['command' => $command->getName(), '--environment' => 'development', '--count' => 5],
['decorated' => false],
);

$this->assertStringContainsString('using environment development', $commandTester->getDisplay());
$this->assertSame(AbstractCommand::CODE_SUCCESS, $exitCode);
}

public function testExecuteWithError(): void
{
$exception = new RuntimeException('oops');
Expand Down
18 changes: 18 additions & 0 deletions tests/Phinx/Migration/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,24 @@ public function testRollbackToVersion($availableRollbacks, $version, $expectedOu
}
}

public function testMigrationByCount(): void
{
$adapter = $this->prepareEnvironment([
'migrations' => $this->getCorrectedPath(__DIR__ . '/_files/reversiblemigrations'),
]);

$this->manager->migrateToCount('production', 2);

$this->assertTrue($adapter->hasTable('info'));
$this->assertFalse($adapter->hasTable('statuses'));
$this->assertTrue($adapter->hasTable('users'));

$this->manager->migrateToCount('production', 1);
$this->assertFalse($adapter->hasTable('info'));
$this->assertTrue($adapter->hasTable('statuses'));
$this->assertTrue($adapter->hasTable('users'));
}

/**
* Test that rollbacking to version chooses the correct
* migration (with namespace) to point to.
Expand Down
Loading