From b99439613cc2ca553c3be17eedd690b981ca9233 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Till=20H=C3=B6rner?= <thoerner@3pc.de>
Date: Wed, 28 Aug 2024 18:01:00 +0200
Subject: [PATCH] [FEATURE] Add console command to mark upgrade wizards as
 undone
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

A new CLI command `typo3 upgrade:mark:undone` has been introduced
that allows to mark a previously executed upgrade wizard as undone
so it can be run again. This makes the existing functionality
from the install tool also available on CLI.

Resolves: #104655
Releases: main
Change-Id: I0d4601e3e81b447793586ddfc31e10bd40a87e64
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/85672
Tested-by: core-ci <typo3@b13.com>
Tested-by: Simon Praetorius <simon@praetorius.me>
Reviewed-by: Simon Praetorius <simon@praetorius.me>
Reviewed-by: Garvin Hicking <gh@faktor-e.de>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: Garvin Hicking <gh@faktor-e.de>
Tested-by: Stefan Bürk <stefan@buerk.tech>
---
 ...oleCommandToMarkUpgradeWizardsAsUndone.rst | 33 +++++++
 .../UpgradeWizardMarkUndoneCommand.php        | 87 +++++++++++++++++++
 .../install/Classes/ServiceProvider.php       | 14 +++
 3 files changed, 134 insertions(+)
 create mode 100644 typo3/sysext/core/Documentation/Changelog/13.3/Feature-104655-AddConsoleCommandToMarkUpgradeWizardsAsUndone.rst
 create mode 100644 typo3/sysext/install/Classes/Command/UpgradeWizardMarkUndoneCommand.php

diff --git a/typo3/sysext/core/Documentation/Changelog/13.3/Feature-104655-AddConsoleCommandToMarkUpgradeWizardsAsUndone.rst b/typo3/sysext/core/Documentation/Changelog/13.3/Feature-104655-AddConsoleCommandToMarkUpgradeWizardsAsUndone.rst
new file mode 100644
index 000000000000..104927e113be
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/13.3/Feature-104655-AddConsoleCommandToMarkUpgradeWizardsAsUndone.rst
@@ -0,0 +1,33 @@
+.. include:: /Includes.rst.txt
+
+.. _feature-104655-1724859386:
+
+========================================================================
+Feature: #104655 - Add console command to mark upgrade wizards as undone
+========================================================================
+
+See :issue:`104655`
+
+Description
+===========
+
+A new CLI command :bash:`typo3 upgrade:mark:undone` has been
+introduced. It allows to mark a previously executed upgrade wizard as "undone",
+so it can be run again.
+
+This makes the existing functionality from the install tool also available on
+CLI.
+
+..  note::
+
+    Bear in mind that wizards theoretically can cause data inconsistencies when
+    being run again. Also, a wizard may not run properly again when its
+    pre-requisites no longer apply after its first run.
+
+Impact
+======
+
+You can now mark an already executed upgrade wizard as "undone" with
+:bash:`typo3 upgrade:markUndone <wizardIdentifier>`
+
+.. index:: CLI, ext:install
diff --git a/typo3/sysext/install/Classes/Command/UpgradeWizardMarkUndoneCommand.php b/typo3/sysext/install/Classes/Command/UpgradeWizardMarkUndoneCommand.php
new file mode 100644
index 000000000000..d39d30f5c30c
--- /dev/null
+++ b/typo3/sysext/install/Classes/Command/UpgradeWizardMarkUndoneCommand.php
@@ -0,0 +1,87 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Install\Command;
+
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputArgument;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
+use TYPO3\CMS\Core\Authentication\CommandLineUserAuthentication;
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Install\Service\LateBootService;
+use TYPO3\CMS\Install\Service\UpgradeWizardsService;
+
+/**
+ * Upgrade wizard command for marking wizards as undone
+ *
+ * @internal
+ */
+class UpgradeWizardMarkUndoneCommand extends Command
+{
+    private UpgradeWizardsService $upgradeWizardsService;
+
+    public function __construct(
+        string $name,
+        private readonly LateBootService $lateBootService
+    ) {
+        parent::__construct($name);
+    }
+
+    /**
+     * Bootstrap running of upgradeWizards
+     */
+    protected function bootstrap(): void
+    {
+        $this->upgradeWizardsService = $this->lateBootService
+            ->loadExtLocalconfDatabaseAndExtTables(false)
+            ->get(UpgradeWizardsService::class);
+        Bootstrap::initializeBackendUser(CommandLineUserAuthentication::class);
+        Bootstrap::initializeBackendAuthentication();
+    }
+
+    /**
+     * Configure the command by defining the name, options and arguments
+     */
+    protected function configure(): void
+    {
+        $this->setDescription('Mark upgrade wizard as undone.')
+            ->addArgument(
+                'wizardIdentifier',
+                InputArgument::REQUIRED
+            );
+    }
+
+    /**
+     * Mark an upgrade wizard as undone
+     */
+    protected function execute(InputInterface $input, OutputInterface $output): int
+    {
+        $io = new SymfonyStyle($input, $output);
+        $this->bootstrap();
+        $wizardIdentifier = (string)$input->getArgument('wizardIdentifier');
+        $wizardInformation = $this->upgradeWizardsService->getWizardInformationByIdentifier($wizardIdentifier);
+        $hasBeenMarkedUndone = $this->upgradeWizardsService->markWizardUndone($wizardIdentifier);
+        if ($hasBeenMarkedUndone) {
+            $io->success('The wizard "' . $wizardInformation['title'] . '" has been marked as undone.');
+            return Command::SUCCESS;
+        }
+        $io->error('The wizard "' . $wizardInformation['title'] . '" could not be marked undone, because it was most likely not yet run.');
+        return Command::FAILURE;
+    }
+}
diff --git a/typo3/sysext/install/Classes/ServiceProvider.php b/typo3/sysext/install/Classes/ServiceProvider.php
index 45acdc612da6..2a512cf16d89 100644
--- a/typo3/sysext/install/Classes/ServiceProvider.php
+++ b/typo3/sysext/install/Classes/ServiceProvider.php
@@ -104,6 +104,7 @@ class ServiceProvider extends AbstractServiceProvider
             Command\LanguagePackCommand::class => self::getLanguagePackCommand(...),
             Command\UpgradeWizardRunCommand::class => self::getUpgradeWizardRunCommand(...),
             Command\UpgradeWizardListCommand::class => self::getUpgradeWizardListCommand(...),
+            Command\UpgradeWizardMarkUndoneCommand::class => self::getUpgradeWizardMarkUndoneCommand(...),
             Command\SetupCommand::class => self::getSetupCommand(...),
             Command\SetupDefaultBackendUserGroupsCommand::class => self::getSetupDefaultBackendUserGroupsCommand(...),
             Database\PermissionsCheck::class => self::getPermissionsCheck(...),
@@ -396,6 +397,14 @@ class ServiceProvider extends AbstractServiceProvider
         );
     }
 
+    public static function getUpgradeWizardMarkUndoneCommand(ContainerInterface $container): Command\UpgradeWizardMarkUndoneCommand
+    {
+        return new Command\UpgradeWizardMarkUndoneCommand(
+            'upgrade:mark:undone',
+            $container->get(Service\LateBootService::class),
+        );
+    }
+
     public static function getSetupCommand(ContainerInterface $container): Command\SetupCommand
     {
         return new Command\SetupCommand(
@@ -455,6 +464,11 @@ class ServiceProvider extends AbstractServiceProvider
             Command\UpgradeWizardListCommand::class,
             'List available upgrade wizards.'
         );
+        $commandRegistry->addLazyCommand(
+            'upgrade:mark:undone',
+            Command\UpgradeWizardMarkUndoneCommand::class,
+            'Mark upgrade wizard as undone.'
+        );
         $commandRegistry->addLazyCommand(
             'setup',
             Command\SetupCommand::class,
-- 
GitLab