Skip to content

Commit

Permalink
added list command
Browse files Browse the repository at this point in the history
# Conflicts:
#	lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php
  • Loading branch information
goetas committed Jan 15, 2020
1 parent b31e429 commit 178531b
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 156 deletions.
2 changes: 2 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ please refer to the [Code BC breaks](#code-bc-breaks) section.
please update your scripts.
Console output is not covered by the BC promise, so please try not to rely on specific a output.
Different levels of verbosity are available now (`-v`, `-vv` and `-vvv` ).
- The `--show-versions` option from `migrations:status` command has been removed,
use `migrations:list` instead.

## Migrations table

Expand Down
4 changes: 3 additions & 1 deletion docs/en/reference/custom-configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,12 @@ Once you have your custom integration setup, you can modify it to look like the
new Command\ExecuteCommand($dependencyFactory),
new Command\GenerateCommand($dependencyFactory),
new Command\LatestCommand($dependencyFactory),
new Command\ListCommand($dependencyFactory),
new Command\MigrateCommand($dependencyFactory),
new Command\RollupCommand($dependencyFactory),
new Command\StatusCommand($dependencyFactory),
new Command\VersionCommand($dependencyFactory)
new Command\VersionCommand($dependencyFactory),
new Command\SyncMetadataCommand($dependencyFactory),
));
$cli->run();
Expand Down
4 changes: 3 additions & 1 deletion docs/en/reference/custom-integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ Now place the following code in the ``migrations`` file:
new Command\ExecuteCommand($dependencyFactory),
new Command\GenerateCommand($dependencyFactory),
new Command\LatestCommand($dependencyFactory),
new Command\ListCommand($dependencyFactory),
new Command\MigrateCommand($dependencyFactory),
new Command\RollupCommand($dependencyFactory),
new Command\StatusCommand($dependencyFactory),
new Command\VersionCommand($dependencyFactory)
new Command\VersionCommand($dependencyFactory),
new Command\ListCommand($dependencyFactory),
));
$cli->run();
Expand Down
128 changes: 128 additions & 0 deletions lib/Doctrine/Migrations/Tools/Console/Command/ListCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
<?php

declare(strict_types=1);

namespace Doctrine\Migrations\Tools\Console\Command;

use DateTimeInterface;
use Doctrine\Migrations\Metadata\AvailableMigration;
use Doctrine\Migrations\Metadata\AvailableMigrationsList;
use Doctrine\Migrations\Metadata\ExecutedMigration;
use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
use Doctrine\Migrations\Version\Version;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use function array_map;
use function array_merge;
use function array_unique;
use function uasort;

/**
* The ListCommand class is responsible for outputting a list of all available migrations and their status.
*/
final class ListCommand extends DoctrineCommand
{
/** @var string */
protected static $defaultName = 'migrations:list';

protected function configure() : void
{
$this
->setAliases(['list-migrations'])
->setDescription('Display a list of all available migrations and their status.')
->setHelp(<<<EOT
The <info>%command.name%</info> command outputs a list of all available migrations and their status:
<info>%command.full_name%</info>
EOT
);

parent::configure();
}

public function execute(InputInterface $input, OutputInterface $output) : int
{
$this->showVersions(
$this->getDependencyFactory()->getMigrationRepository()->getMigrations(), // available migrations
$this->getDependencyFactory()->getMetadataStorage()->getExecutedMigrations(), // executed migrations
$output
);

return 0;
}

private function showVersions(
AvailableMigrationsList $availableMigrations,
ExecutedMigrationsSet $executedMigrations,
OutputInterface $output
) : void {
$table = new Table($output);
$table->setHeaders(
[
[new TableCell('Migration Versions', ['colspan' => 4])],
['Migration', 'Status', 'Migrated At', 'Execution Time', 'Description'],
]
);

foreach ($this->getSortedVersions($availableMigrations, $executedMigrations) as $version) {
$description = null;
$executedAt = null;
$executionTime = null;

if ($executedMigrations->hasMigration($version)) {
$executedMigration = $executedMigrations->getMigration($version);
$executionTime = $executedMigration->getExecutionTime();
$executedAt = $executedMigration->getExecutedAt() instanceof DateTimeInterface
? $executedMigration->getExecutedAt()->format('Y-m-d H:i:s')
: null;
}

if ($availableMigrations->hasMigration($version)) {
$description = $availableMigrations->getMigration($version)->getMigration()->getDescription();
}

if ($executedMigrations->hasMigration($version) && $availableMigrations->hasMigration($version)) {
$status = '<info>migrated</info>';
} elseif ($executedMigrations->hasMigration($version)) {
$status = '<error>migrated, not available</error>';
} else {
$status = '<comment>not migrated</comment>';
}

$table->addRow([
(string) $version,
$status,
(string) $executedAt,
$executionTime !== null ? $executionTime . 's': '',
$description,
]);
}

$table->render();
}

/**
* @return Version[]
*/
private function getSortedVersions(AvailableMigrationsList $availableMigrations, ExecutedMigrationsSet $executedMigrations) : array
{
$availableVersions = array_map(static function (AvailableMigration $availableMigration) : Version {
return $availableMigration->getVersion();
}, $availableMigrations->getItems());

$executedVersions = array_map(static function (ExecutedMigration $executedMigration) : Version {
return $executedMigration->getVersion();
}, $executedMigrations->getItems());

$versions = array_unique(array_merge($availableVersions, $executedVersions));

$comparator = $this->getDependencyFactory()->getVersionComparator();
uasort($versions, static function (Version $a, Version $b) use ($comparator) : int {
return $comparator->compare($a, $b);
});

return $versions;
}
}
77 changes: 0 additions & 77 deletions lib/Doctrine/Migrations/Tools/Console/Command/StatusCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@

namespace Doctrine\Migrations\Tools\Console\Command;

use DateTimeImmutable;
use Doctrine\Migrations\Metadata\AvailableMigrationsList;
use Doctrine\Migrations\Metadata\ExecutedMigrationsSet;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use function count;

/**
* The StatusCommand class is responsible for outputting what the current state is of all your migrations. It shows
Expand All @@ -38,10 +32,6 @@ protected function configure() : void
The <info>%command.name%</info> command outputs the status of a set of migrations:
<info>%command.full_name%</info>
You can output a list of all available migrations and their status with <comment>--show-versions</comment>:
<info>%command.full_name% --show-versions</info>
EOT
);

Expand All @@ -63,73 +53,6 @@ public function execute(InputInterface $input, OutputInterface $output) : ?int
$infosHelper = $this->getDependencyFactory()->getMigrationStatusInfosHelper();
$infosHelper->showMigrationsInfo($output, $availableMigrations, $executedMigrations, $newMigrations, $executedUnavailableMigrations);

if ($input->getOption('show-versions') === false) {
return 0;
}

if (count($availableMigrations) !== 0) {
$this->showVersions($availableMigrations, $executedMigrations, $output);
}

if (count($executedUnavailableMigrations) !== 0) {
$this->showUnavailableVersions($output, $executedUnavailableMigrations);
}

return 0;
}

private function showUnavailableVersions(OutputInterface $output, ExecutedMigrationsSet $executedUnavailableMigrations) : void
{
$table = new Table($output);
$table->setHeaders(
[
[new TableCell('<error>Previously Executed Unavailable Migration Versions</error>', ['colspan' => 2])],
['Migration', 'Migrated At'],
]
);
foreach ($executedUnavailableMigrations->getItems() as $executedUnavailableMigration) {
$table->addRow([
(string) $executedUnavailableMigration->getVersion(),
$executedUnavailableMigration->getExecutedAt() !== null
? $executedUnavailableMigration->getExecutedAt()->format('Y-m-d H:i:s')
: null,
]);
}

$table->render();
}

private function showVersions(
AvailableMigrationsList $availableMigrationsSet,
ExecutedMigrationsSet $executedMigrationsSet,
OutputInterface $output
) : void {
$table = new Table($output);
$table->setHeaders(
[
[new TableCell('Available Migration Versions', ['colspan' => 4])],
['Migration', 'Migrated', 'Migrated At', 'Description'],
]
);
foreach ($availableMigrationsSet->getItems() as $availableMigration) {
$executedMigration = $executedMigrationsSet->hasMigration($availableMigration->getVersion())
? $executedMigrationsSet->getMigration($availableMigration->getVersion())
: null;

$executedAt = $executedMigration!==null && $executedMigration->getExecutedAt() instanceof DateTimeImmutable
? $executedMigration->getExecutedAt()->format('Y-m-d H:i:s')
: null;

$description = $availableMigration->getMigration()->getDescription();

$table->addRow([
(string) $availableMigration->getVersion(),
$executedMigration !== null ? '<comment>migrated</comment>' : '<error>not migrated</error>',
(string) $executedAt,
$description,
]);
}

$table->render();
}
}
2 changes: 2 additions & 0 deletions lib/Doctrine/Migrations/Tools/Console/ConsoleRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Doctrine\Migrations\Tools\Console\Command\ExecuteCommand;
use Doctrine\Migrations\Tools\Console\Command\GenerateCommand;
use Doctrine\Migrations\Tools\Console\Command\LatestCommand;
use Doctrine\Migrations\Tools\Console\Command\ListCommand;
use Doctrine\Migrations\Tools\Console\Command\MigrateCommand;
use Doctrine\Migrations\Tools\Console\Command\RollupCommand;
use Doctrine\Migrations\Tools\Console\Command\StatusCommand;
Expand Down Expand Up @@ -109,6 +110,7 @@ public static function addCommands(Application $cli, ?DependencyFactory $depende
new VersionCommand($dependencyFactory),
new UpToDateCommand($dependencyFactory),
new SyncMetadataCommand($dependencyFactory),
new ListCommand($dependencyFactory),
]);

if ($dependencyFactory === null || ! $dependencyFactory->hasEntityManager()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

declare(strict_types=1);

namespace Doctrine\Migrations\Tests\Tools\Console\Command;

use DateTimeImmutable;
use Doctrine\Migrations\AbstractMigration;
use Doctrine\Migrations\Configuration\Configuration;
use Doctrine\Migrations\Configuration\Connection\ExistingConnection;
use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Metadata\Storage\MetadataStorage;
use Doctrine\Migrations\Metadata\Storage\TableMetadataStorageConfiguration;
use Doctrine\Migrations\MigrationRepository;
use Doctrine\Migrations\Tests\MigrationTestCase;
use Doctrine\Migrations\Tools\Console\Command\ListCommand;
use Doctrine\Migrations\Version\Direction;
use Doctrine\Migrations\Version\ExecutionResult;
use Doctrine\Migrations\Version\Version;
use Symfony\Component\Console\Tester\CommandTester;
use function array_map;
use function explode;
use function sys_get_temp_dir;
use function trim;

class ListCommandTest extends MigrationTestCase
{
/** @var ListCommand */
private $command;

/** @var MigrationRepository */
private $migrationRepository;

/** @var MetadataStorage */
private $metadataStorage;

/** @var CommandTester */
private $commandTester;

protected function setUp() : void
{
$configuration = new Configuration();
$configuration->setMetadataStorageConfiguration(new TableMetadataStorageConfiguration());
$configuration->addMigrationsDirectory('DoctrineMigrations', sys_get_temp_dir());

$conn = $this->getSqliteConnection();

$dependencyFactory = DependencyFactory::fromConnection(
new Configuration\ExistingConfiguration($configuration),
new ExistingConnection($conn)
);

$this->migrationRepository = $dependencyFactory->getMigrationRepository();
$this->metadataStorage = $dependencyFactory->getMetadataStorage();

$this->metadataStorage->ensureInitialized();

$this->command = new ListCommand($dependencyFactory);
$this->commandTester = new CommandTester($this->command);
}

public function testExecute() : void
{
$migrationClass = $this->createMock(AbstractMigration::class);
$migrationClass
->expects(self::atLeastOnce())
->method('getDescription')
->willReturn('foo');

$this->migrationRepository->registerMigrationInstance(new Version('1231'), $migrationClass);
$this->migrationRepository->registerMigrationInstance(new Version('1230'), $migrationClass);

$result = new ExecutionResult(new Version('1230'), Direction::UP, new DateTimeImmutable('2010-01-01 02:03:04'));
$result->setTime(10.0);
$this->metadataStorage->complete($result);

$result = new ExecutionResult(new Version('1229'), Direction::UP, new DateTimeImmutable('2010-01-01 02:03:04'));
$this->metadataStorage->complete($result);

$this->commandTester->execute([]);

$lines = array_map('trim', explode("\n", trim($this->commandTester->getDisplay(true))));

self::assertSame(
[
0 => '+-----------+-------------------------+---------------------+----------------+-------------+',
1 => '| Migration Versions | |',
2 => '+-----------+-------------------------+---------------------+----------------+-------------+',
3 => '| Migration | Status | Migrated At | Execution Time | Description |',
4 => '+-----------+-------------------------+---------------------+----------------+-------------+',
5 => '| 1229 | migrated, not available | 2010-01-01 02:03:04 | | |',
6 => '| 1230 | migrated | 2010-01-01 02:03:04 | 10s | foo |',
7 => '| 1231 | not migrated | | | foo |',
8 => '+-----------+-------------------------+---------------------+----------------+-------------+',
],
$lines
);
}
}
Loading

0 comments on commit 178531b

Please sign in to comment.