StatusCommand.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2017-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2017 ownCloud GmbH
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OC\Core\Command\Db\Migrations;
  8. use OC\DB\Connection;
  9. use OC\DB\MigrationService;
  10. use OC\Migration\ConsoleOutput;
  11. use Stecman\Component\Symfony\Console\BashCompletion\Completion\CompletionAwareInterface;
  12. use Stecman\Component\Symfony\Console\BashCompletion\CompletionContext;
  13. use Symfony\Component\Console\Command\Command;
  14. use Symfony\Component\Console\Input\InputArgument;
  15. use Symfony\Component\Console\Input\InputInterface;
  16. use Symfony\Component\Console\Output\OutputInterface;
  17. class StatusCommand extends Command implements CompletionAwareInterface {
  18. public function __construct(
  19. private Connection $connection,
  20. ) {
  21. parent::__construct();
  22. }
  23. protected function configure() {
  24. $this
  25. ->setName('migrations:status')
  26. ->setDescription('View the status of a set of migrations.')
  27. ->addArgument('app', InputArgument::REQUIRED, 'Name of the app this migration command shall work on');
  28. }
  29. public function execute(InputInterface $input, OutputInterface $output): int {
  30. $appName = $input->getArgument('app');
  31. $ms = new MigrationService($appName, $this->connection, new ConsoleOutput($output));
  32. $infos = $this->getMigrationsInfos($ms);
  33. foreach ($infos as $key => $value) {
  34. if (is_array($value)) {
  35. $output->writeln(" <comment>>></comment> $key:");
  36. foreach ($value as $subKey => $subValue) {
  37. $output->writeln(" <comment>>></comment> $subKey: " . str_repeat(' ', 46 - strlen($subKey)) . $subValue);
  38. }
  39. } else {
  40. $output->writeln(" <comment>>></comment> $key: " . str_repeat(' ', 50 - strlen($key)) . $value);
  41. }
  42. }
  43. return 0;
  44. }
  45. /**
  46. * @param string $optionName
  47. * @param CompletionContext $context
  48. * @return string[]
  49. */
  50. public function completeOptionValues($optionName, CompletionContext $context) {
  51. return [];
  52. }
  53. /**
  54. * @param string $argumentName
  55. * @param CompletionContext $context
  56. * @return string[]
  57. */
  58. public function completeArgumentValues($argumentName, CompletionContext $context) {
  59. if ($argumentName === 'app') {
  60. $allApps = \OC_App::getAllApps();
  61. return array_diff($allApps, \OC_App::getEnabledApps(true, true));
  62. }
  63. return [];
  64. }
  65. /**
  66. * @param MigrationService $ms
  67. * @return array associative array of human readable info name as key and the actual information as value
  68. */
  69. public function getMigrationsInfos(MigrationService $ms) {
  70. $executedMigrations = $ms->getMigratedVersions();
  71. $availableMigrations = $ms->getAvailableVersions();
  72. $executedUnavailableMigrations = array_diff($executedMigrations, array_keys($availableMigrations));
  73. $numExecutedUnavailableMigrations = count($executedUnavailableMigrations);
  74. $numNewMigrations = count(array_diff(array_keys($availableMigrations), $executedMigrations));
  75. $pending = $ms->describeMigrationStep('lastest');
  76. $infos = [
  77. 'App' => $ms->getApp(),
  78. 'Version Table Name' => $ms->getMigrationsTableName(),
  79. 'Migrations Namespace' => $ms->getMigrationsNamespace(),
  80. 'Migrations Directory' => $ms->getMigrationsDirectory(),
  81. 'Previous Version' => $this->getFormattedVersionAlias($ms, 'prev'),
  82. 'Current Version' => $this->getFormattedVersionAlias($ms, 'current'),
  83. 'Next Version' => $this->getFormattedVersionAlias($ms, 'next'),
  84. 'Latest Version' => $this->getFormattedVersionAlias($ms, 'latest'),
  85. 'Executed Migrations' => count($executedMigrations),
  86. 'Executed Unavailable Migrations' => $numExecutedUnavailableMigrations,
  87. 'Available Migrations' => count($availableMigrations),
  88. 'New Migrations' => $numNewMigrations,
  89. 'Pending Migrations' => count($pending) ? $pending : 'None'
  90. ];
  91. return $infos;
  92. }
  93. /**
  94. * @param MigrationService $migrationService
  95. * @param string $alias
  96. * @return mixed|null|string
  97. */
  98. private function getFormattedVersionAlias(MigrationService $migrationService, $alias) {
  99. $migration = $migrationService->getMigration($alias);
  100. //No version found
  101. if ($migration === null) {
  102. if ($alias === 'next') {
  103. return 'Already at latest migration step';
  104. }
  105. if ($alias === 'prev') {
  106. return 'Already at first migration step';
  107. }
  108. }
  109. return $migration;
  110. }
  111. }