Repair.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  5. * SPDX-License-Identifier: AGPL-3.0-only
  6. */
  7. namespace OC\Core\Command\Maintenance;
  8. use Exception;
  9. use OC\Repair\Events\RepairAdvanceEvent;
  10. use OC\Repair\Events\RepairErrorEvent;
  11. use OC\Repair\Events\RepairFinishEvent;
  12. use OC\Repair\Events\RepairInfoEvent;
  13. use OC\Repair\Events\RepairStartEvent;
  14. use OC\Repair\Events\RepairStepEvent;
  15. use OC\Repair\Events\RepairWarningEvent;
  16. use OCP\App\IAppManager;
  17. use OCP\EventDispatcher\Event;
  18. use OCP\EventDispatcher\IEventDispatcher;
  19. use OCP\IConfig;
  20. use Symfony\Component\Console\Command\Command;
  21. use Symfony\Component\Console\Helper\ProgressBar;
  22. use Symfony\Component\Console\Input\InputInterface;
  23. use Symfony\Component\Console\Input\InputOption;
  24. use Symfony\Component\Console\Output\OutputInterface;
  25. class Repair extends Command {
  26. private ProgressBar $progress;
  27. private OutputInterface $output;
  28. protected bool $errored = false;
  29. public function __construct(
  30. protected \OC\Repair $repair,
  31. protected IConfig $config,
  32. private IEventDispatcher $dispatcher,
  33. private IAppManager $appManager,
  34. ) {
  35. parent::__construct();
  36. }
  37. protected function configure() {
  38. $this
  39. ->setName('maintenance:repair')
  40. ->setDescription('repair this installation')
  41. ->addOption(
  42. 'include-expensive',
  43. null,
  44. InputOption::VALUE_NONE,
  45. 'Use this option when you want to include resource and load expensive tasks');
  46. }
  47. protected function execute(InputInterface $input, OutputInterface $output): int {
  48. $repairSteps = $this->repair::getRepairSteps();
  49. if ($input->getOption('include-expensive')) {
  50. $repairSteps = array_merge($repairSteps, $this->repair::getExpensiveRepairSteps());
  51. }
  52. foreach ($repairSteps as $step) {
  53. $this->repair->addStep($step);
  54. }
  55. $apps = $this->appManager->getInstalledApps();
  56. foreach ($apps as $app) {
  57. if (!$this->appManager->isEnabledForUser($app)) {
  58. continue;
  59. }
  60. $info = $this->appManager->getAppInfo($app);
  61. if (!is_array($info)) {
  62. continue;
  63. }
  64. \OC_App::loadApp($app);
  65. $steps = $info['repair-steps']['post-migration'];
  66. foreach ($steps as $step) {
  67. try {
  68. $this->repair->addStep($step);
  69. } catch (Exception $ex) {
  70. $output->writeln("<error>Failed to load repair step for $app: {$ex->getMessage()}</error>");
  71. }
  72. }
  73. }
  74. $maintenanceMode = $this->config->getSystemValueBool('maintenance');
  75. $this->config->setSystemValue('maintenance', true);
  76. $this->progress = new ProgressBar($output);
  77. $this->output = $output;
  78. $this->dispatcher->addListener(RepairStartEvent::class, [$this, 'handleRepairFeedBack']);
  79. $this->dispatcher->addListener(RepairAdvanceEvent::class, [$this, 'handleRepairFeedBack']);
  80. $this->dispatcher->addListener(RepairFinishEvent::class, [$this, 'handleRepairFeedBack']);
  81. $this->dispatcher->addListener(RepairStepEvent::class, [$this, 'handleRepairFeedBack']);
  82. $this->dispatcher->addListener(RepairInfoEvent::class, [$this, 'handleRepairFeedBack']);
  83. $this->dispatcher->addListener(RepairWarningEvent::class, [$this, 'handleRepairFeedBack']);
  84. $this->dispatcher->addListener(RepairErrorEvent::class, [$this, 'handleRepairFeedBack']);
  85. $this->repair->run();
  86. $this->config->setSystemValue('maintenance', $maintenanceMode);
  87. return $this->errored ? 1 : 0;
  88. }
  89. public function handleRepairFeedBack(Event $event): void {
  90. if ($event instanceof RepairStartEvent) {
  91. $this->progress->start($event->getMaxStep());
  92. } elseif ($event instanceof RepairAdvanceEvent) {
  93. $this->progress->advance($event->getIncrement());
  94. } elseif ($event instanceof RepairFinishEvent) {
  95. $this->progress->finish();
  96. $this->output->writeln('');
  97. } elseif ($event instanceof RepairStepEvent) {
  98. $this->output->writeln('<info> - ' . $event->getStepName() . '</info>');
  99. } elseif ($event instanceof RepairInfoEvent) {
  100. $this->output->writeln('<info> - ' . $event->getMessage() . '</info>');
  101. } elseif ($event instanceof RepairWarningEvent) {
  102. $this->output->writeln('<comment> - WARNING: ' . $event->getMessage() . '</comment>');
  103. } elseif ($event instanceof RepairErrorEvent) {
  104. $this->output->writeln('<error> - ERROR: ' . $event->getMessage() . '</error>');
  105. $this->errored = true;
  106. }
  107. }
  108. }