aboutsummaryrefslogtreecommitdiffstats
path: root/core/Command/Db/Migrations/PreviewCommand.php
blob: b1881a0c42c41fd3c000e8f5c7b56ee99de6ae49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?php

declare(strict_types=1);

/**
 * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */
namespace OC\Core\Command\Db\Migrations;

use OC\Migration\MetadataManager;
use OC\Updater\ReleaseMetadata;
use OCP\Migration\Attributes\MigrationAttribute;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Helper\TableCellStyle;
use Symfony\Component\Console\Helper\TableSeparator;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class PreviewCommand extends Command {
	private bool $initiated = false;
	public function __construct(
		private readonly MetadataManager $metadataManager,
		private readonly ReleaseMetadata $releaseMetadata,
	) {
		parent::__construct();
	}

	protected function configure(): void {
		$this
			->setName('migrations:preview')
			->setDescription('Get preview of available DB migrations in case of initiating an upgrade')
			->addArgument('version', InputArgument::REQUIRED, 'The destination version number');

		parent::configure();
	}

	public function execute(InputInterface $input, OutputInterface $output): int {
		$version = $input->getArgument('version');
		if (filter_var($version, FILTER_VALIDATE_URL)) {
			$metadata = $this->releaseMetadata->downloadMetadata($version);
		} elseif (str_starts_with($version, '/')) {
			$metadata = json_decode(file_get_contents($version), true, flags: JSON_THROW_ON_ERROR);
		} else {
			$metadata = $this->releaseMetadata->getMetadata($version);
		}

		$parsed = $this->metadataManager->getMigrationsAttributesFromReleaseMetadata($metadata['migrations'] ?? [], true);

		$table = new Table($output);
		$this->displayMigrations($table, 'core', $parsed['core'] ?? []);
		foreach ($parsed['apps'] as $appId => $migrations) {
			if (!empty($migrations)) {
				$this->displayMigrations($table, $appId, $migrations);
			}
		}
		$table->render();

		return 0;
	}

	private function displayMigrations(Table $table, string $appId, array $data): void {
		if (empty($data)) {
			return;
		}

		if ($this->initiated) {
			$table->addRow(new TableSeparator());
		}
		$this->initiated = true;

		$table->addRow(
			[
				new TableCell(
					$appId,
					[
						'colspan' => 2,
						'style' => new TableCellStyle(['cellFormat' => '<info>%s</info>'])
					]
				)
			]
		)->addRow(new TableSeparator());

		/** @var MigrationAttribute[] $attributes */
		foreach($data as $migration => $attributes) {
			$attributesStr = [];
			foreach($attributes as $attribute) {
				$definition = '<info>' . $attribute->definition() . "</info>";
				$definition .= empty($attribute->getDescription()) ? '' : "\n  " . $attribute->getDescription();
				$definition .= empty($attribute->getNotes()) ? '' : "\n  <comment>" . implode("</comment>\n  <comment>", $attribute->getNotes()) . '</comment>';
				$attributesStr[] = $definition;
			}
			$table->addRow([$migration, implode("\n", $attributesStr)]);
		}
	}
}