[TASK] Migrate upgrade wizards in install extension 93/58293/8
authorChristian Kuhn <lolli@schwarzbu.ch>
Sun, 16 Sep 2018 13:06:09 +0000 (15:06 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Wed, 19 Sep 2018 12:30:48 +0000 (14:30 +0200)
Resolves: #86201
Related: #86172
Releases: master
Change-Id: I9d38ca04ee8a71ff6ffa325a2f0ce2c8c6cde183
Reviewed-on: https://review.typo3.org/58293
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
30 files changed:
typo3/sysext/install/Classes/Controller/UpgradeController.php
typo3/sysext/install/Classes/Updates/AbstractDownloadExtensionUpdate.php
typo3/sysext/install/Classes/Updates/BackendLayoutIconUpdateWizard.php
typo3/sysext/install/Classes/Updates/BackendUserStartModuleUpdate.php
typo3/sysext/install/Classes/Updates/BulletContentElementUpdate.php
typo3/sysext/install/Classes/Updates/ChattyInterface.php
typo3/sysext/install/Classes/Updates/CommandLineBackendUserRemovalUpdate.php
typo3/sysext/install/Classes/Updates/DatabaseRowsUpdateWizard.php
typo3/sysext/install/Classes/Updates/DatabaseUpdatedPrerequisite.php
typo3/sysext/install/Classes/Updates/ExtensionManagerTables.php
typo3/sysext/install/Classes/Updates/FileReferenceUpdate.php
typo3/sysext/install/Classes/Updates/FillTranslationSourceField.php
typo3/sysext/install/Classes/Updates/FrontendUserImageUpdateWizard.php
typo3/sysext/install/Classes/Updates/LanguageSortingUpdate.php
typo3/sysext/install/Classes/Updates/MigrateFeSessionDataUpdate.php
typo3/sysext/install/Classes/Updates/MigrateFscStaticTemplateUpdate.php
typo3/sysext/install/Classes/Updates/MigratePagesLanguageOverlayUpdate.php
typo3/sysext/install/Classes/Updates/MigrateUrlTypesInPagesUpdate.php
typo3/sysext/install/Classes/Updates/PopulatePageSlugs.php
typo3/sysext/install/Classes/Updates/RedirectsExtensionUpdate.php
typo3/sysext/install/Classes/Updates/ReferenceIndexUpdatedPrerequisite.php
typo3/sysext/install/Classes/Updates/SectionFrameToFrameClassUpdate.php
typo3/sysext/install/Classes/Updates/SeparateSysHistoryFromSysLogUpdate.php
typo3/sysext/install/Classes/Updates/SplitMenusUpdate.php
typo3/sysext/install/Classes/Updates/StartModuleUpdate.php
typo3/sysext/install/Classes/Updates/UploadContentElementUpdate.php
typo3/sysext/install/Classes/Updates/WizardDoneToRegistry.php
typo3/sysext/install/Resources/Private/Templates/Upgrade/UpgradeWizards.html
typo3/sysext/install/Tests/Functional/Updates/CommandLineBackendUserRemovalUpdateTest.php
typo3/sysext/install/ext_localconf.php

index feb3021..5f0aa4f 100644 (file)
@@ -925,8 +925,7 @@ class UpgradeController extends AbstractController
         $this->loadExtLocalconfDatabaseAndExtTables();
         $upgradeWizardsService = new UpgradeWizardsService();
         $identifier = $request->getParsedBody()['install']['identifier'];
-        $showDatabaseQueries = (int)$request->getParsedBody()['install']['values']['showDatabaseQueries'];
-        $messages = $upgradeWizardsService->executeWizard($identifier, $showDatabaseQueries);
+        $messages = $upgradeWizardsService->executeWizard($identifier);
         return new JsonResponse([
             'success' => true,
             'status' => $messages,
index 3e7fbad..d0f461a 100644 (file)
@@ -44,6 +44,9 @@ abstract class AbstractDownloadExtensionUpdate implements UpgradeWizardInterface
      */
     protected $extension;
 
+    /**
+     * @param OutputInterface $output
+     */
     public function setOutput(OutputInterface $output): void
     {
         $this->output = $output;
@@ -106,16 +109,12 @@ abstract class AbstractDownloadExtensionUpdate implements UpgradeWizardInterface
 
         if ($isComposerMode && !$isExtensionAvailable) {
             $updateSuccessful = false;
-            $this->output->writeln('<warning>The extension ' .
-                              $extensionKey .
-                              ' can not be downloaded since ' .
-                              'Composer is used for package management. Please require this ' .
-                              'extension as package via Composer: ' .
-                              '"composer require ' .
-                              $extension->getComposerName() .
-                              ':^' .
-                              $extension->getVersionString() .
-                              '"</warning>');
+            $this->output->writeln(
+                '<warning>The extension ' . $extensionKey
+                . ' can not be downloaded since Composer is used for package management. Please require this '
+                . 'extension as package via Composer: "composer require ' . $extension->getComposerName()
+                . ':^' . $extension->getVersionString() . '"</warning>'
+            );
         }
 
         if ($updateSuccessful) {
index 85c25ba..ec21eaa 100644 (file)
@@ -17,6 +17,7 @@ namespace TYPO3\CMS\Install\Updates;
 use Doctrine\DBAL\DBALException;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
+use Symfony\Component\Console\Output\OutputInterface;
 use TYPO3\CMS\Core\Core\Environment;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Expression\ExpressionBuilder;
@@ -30,14 +31,14 @@ use TYPO3\CMS\Core\Utility\PathUtility;
  * Upgrade wizard which goes through all files referenced in backend_layout.icon
  * and creates sys_file records as well as sys_file_reference records for each hit.
  */
-class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwareInterface
+class BackendLayoutIconUpdateWizard implements UpgradeWizardInterface, ChattyInterface, LoggerAwareInterface
 {
     use LoggerAwareTrait;
 
     /**
-     * @var string
+     * @var OutputInterface
      */
-    protected $title = 'Migrate all file relations from backend_layout.icon to sys_file_references';
+    protected $output;
 
     /**
      * @var ResourceStorage
@@ -74,77 +75,93 @@ class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwar
     protected $targetPath = '_migrated/backend_layouts/';
 
     /**
-     * Checks if an update is needed
-     *
-     * @param string &$description The description for the update
-     *
-     * @return bool TRUE if an update is needed, FALSE otherwise
+     * @return string Unique identifier of this updater
      */
-    public function checkForUpdate(&$description)
+    public function getIdentifier(): string
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
+        return 'backendLayoutIcons';
+    }
 
-        // If there are no valid records, the wizard can be marked as done directly
-        $dbQueries = [];
-        $records = $this->getRecordsFromTable($dbQueries);
-        if (empty($records)) {
-            $this->markWizardAsDone();
-            return false;
-        }
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate all file relations from backend_layout.icon to sys_file_references';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'This update wizard goes through all files that are referenced in the'
+            . ' backend_layout.icon field and adds the files to the FAL File Index.'
+            . ' It also moves the files from uploads/ to the fileadmin/_migrated/ path.';
+    }
+
+    /**
+     * @return bool True if there are records to update
+     */
+    public function updateNecessary(): bool
+    {
+        return !empty($this->getRecordsFromTable());
+    }
 
-        $description = 'This update wizard goes through all files that are referenced in the backend_layout.icon field'
-            . ' and adds the files to the FAL File Index.<br />'
-            . 'It also moves the files from uploads/ to the fileadmin/_migrated/ path.';
+    /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
 
-        return true;
+    /**
+     * @param OutputInterface $output
+     */
+    public function setOutput(OutputInterface $output): void
+    {
+        $this->output = $output;
     }
 
     /**
-     * Performs the database update.
+     * Performs the configuration update.
      *
-     * @param array &$dbQueries Queries done in this update
-     * @param string &$customMessage Custom message
-     * @return bool TRUE on success, FALSE on error
+     * @return bool
      */
-    public function performUpdate(array &$dbQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
-        $customMessage = '';
+        $result = true;
         try {
             $storages = GeneralUtility::makeInstance(StorageRepository::class)->findAll();
             $this->storage = $storages[0];
-
-            $records = $this->getRecordsFromTable($dbQueries);
+            $records = $this->getRecordsFromTable();
             foreach ($records as $record) {
-                $this->migrateField($record, $customMessage, $dbQueries);
+                $this->migrateField($record);
             }
-
-            $this->markWizardAsDone();
         } catch (\Exception $e) {
-            $customMessage .= PHP_EOL . $e->getMessage();
+            // If something goes wrong, migrateField() logs an error
+            $result = false;
         }
-
-        return empty($customMessage);
+        return $result;
     }
 
     /**
      * Get records from table where the field to migrate is not empty (NOT NULL and != '')
      * and also not numeric (which means that it is migrated)
      *
-     * @param array $dbQueries
-     *
      * @return array
      * @throws \RuntimeException
      */
-    protected function getRecordsFromTable(&$dbQueries)
+    protected function getRecordsFromTable()
     {
         $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
         $queryBuilder = $connectionPool->getQueryBuilderForTable($this->table);
         $queryBuilder->getRestrictions()->removeAll();
-
         try {
-            $result = $queryBuilder
+            return $queryBuilder
                 ->select('uid', 'pid', $this->fieldToMigrate)
                 ->from($this->table)
                 ->where(
@@ -160,11 +177,8 @@ class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwar
                     )
                 )
                 ->orderBy('uid')
-                ->execute();
-
-            $dbQueries[] = $queryBuilder->getSQL();
-
-            return $result->fetchAll();
+                ->execute()
+                ->fetchAll();
         } catch (DBALException $e) {
             throw new \RuntimeException(
                 'Database query failed. Error was: ' . $e->getPrevious()->getMessage(),
@@ -177,12 +191,9 @@ class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwar
      * Migrates a single field.
      *
      * @param array $row
-     * @param string $customMessage
-     * @param array $dbQueries
-     *
      * @throws \Exception
      */
-    protected function migrateField($row, &$customMessage, &$dbQueries)
+    protected function migrateField($row)
     {
         $fieldItems = GeneralUtility::trimExplode(',', $row[$this->fieldToMigrate], true);
         if (empty($fieldItems) || is_numeric($row[$this->fieldToMigrate])) {
@@ -240,7 +251,6 @@ class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwar
                     $file = $this->storage->getFile($this->targetPath . $item);
                     $fileUid = $file->getUid();
                 } catch (\InvalidArgumentException $e) {
-
                     // no file found, no reference can be set
                     $this->logger->notice(
                         'File ' . $this->sourcePath . $item . ' does not exist. Reference was not migrated.',
@@ -250,16 +260,14 @@ class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwar
                             'field' => $this->fieldToMigrate,
                         ]
                     );
-
                     $format = 'File \'%s\' does not exist. Referencing field: %s.%d.%s. The reference was not migrated.';
-                    $message = sprintf(
+                    $this->output->writeln(sprintf(
                         $format,
                         $this->sourcePath . $item,
                         $this->table,
                         $row['uid'],
                         $this->fieldToMigrate
-                    );
-                    $customMessage .= PHP_EOL . $message;
+                    ));
                     continue;
                 }
             }
@@ -280,7 +288,6 @@ class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwar
 
                 $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_file_reference');
                 $queryBuilder->insert('sys_file_reference')->values($fields)->execute();
-                $dbQueries[] = str_replace(LF, ' ', $queryBuilder->getSQL());
                 ++$i;
             }
         }
@@ -295,7 +302,6 @@ class BackendLayoutIconUpdateWizard extends AbstractUpdate implements LoggerAwar
                     $queryBuilder->createNamedParameter($row['uid'], \PDO::PARAM_INT)
                 )
             )->set($this->fieldToMigrate, $i)->execute();
-            $dbQueries[] = str_replace(LF, ' ', $queryBuilder->getSQL());
         }
     }
 }
index 041b5de..e29100a 100644 (file)
@@ -20,20 +20,40 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Update backend user setting startModule if set to "help_aboutmodules" or "help_CshmanualCshmanual"
  */
-class BackendUserStartModuleUpdate extends AbstractUpdate
+class BackendUserStartModuleUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Update backend user setting "startModule"';
+    public function getIdentifier(): string
+    {
+        return 'cshmanualBackendUsers';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Update backend user setting "startModule"';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'The backend user setting startModule is changed for the extensions about/aboutmodules'
+            . ' and help/cshmanual. Update all backend users that use EXT:aboutmodules and'
+            . ' EXT:cshmanual as startModule.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
         $statement = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getConnectionForTable('be_users')
@@ -53,22 +73,26 @@ class BackendUserStartModuleUpdate extends AbstractUpdate
                 }
             }
         }
-        if ($needsExecution) {
-            $description = 'The backend user setting startModule is changed for the extensions about/aboutmodules and help/cshmanual. Update all'
-                . ' backend users that use EXT:aboutmodules and EXT:cshmanual as startModule.';
-        }
         return $needsExecution;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update if backend user's startmodule is
      * "help_aboutmodules" or "help_AboutmodulesAboutmodules" or "help_CshmanualCshmanual"
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
         $statement = $queryBuilder->select('uid', 'uc')->from('be_users')->execute();
@@ -95,9 +119,8 @@ class BackendUserStartModuleUpdate extends AbstractUpdate
                         )
                         // Manual quoting and false as third parameter to have the final
                         // value in $databaseQueries and not a statement placeholder
-                        ->set('uc', serialize($userConfig));
-                    $databaseQueries[] = $queryBuilder->getSQL();
-                    $queryBuilder->execute();
+                        ->set('uc', serialize($userConfig))
+                        ->execute();
                 }
             }
         }
index 65c1895..6959010 100644 (file)
@@ -20,24 +20,39 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Migrate bullet content element rendering from layout to bullets_type
  */
-class BulletContentElementUpdate extends AbstractUpdate
+class BulletContentElementUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = '[Optional] Migrate bullet content element rendering selector from layout to bullets_type';
+    public function getIdentifier(): string
+    {
+        return 'bulletContentElementUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate bullet content element rendering selector from layout to bullets_type';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'Rendering type field has been streamlined with fluid_styled_content.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
         $queryBuilder->getRestrictions()->removeAll();
         $elementCount = $queryBuilder->count('uid')
@@ -46,21 +61,27 @@ class BulletContentElementUpdate extends AbstractUpdate
                 $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('bullets', \PDO::PARAM_STR)),
                 $queryBuilder->expr()->in('layout', [1, 2])
             )
-            ->execute()->fetchColumn(0);
-        if ($elementCount) {
-            $description = 'Rendering type field has been streamlined with fluid_styled_content.';
-        }
+            ->execute()
+            ->fetchColumn(0);
         return (bool)$elementCount;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tt_content');
         $queryBuilder = $connection->createQueryBuilder();
@@ -83,10 +104,8 @@ class BulletContentElementUpdate extends AbstractUpdate
                 )
                 ->set('layout', 0, false)
                 ->set('bullets_type', $record['layout']);
-            $databaseQueries[] = $queryBuilder->getSQL();
             $queryBuilder->execute();
         }
-        $this->markWizardAsDone();
         return true;
     }
 }
index 5af9899..f37592d 100644 (file)
@@ -28,7 +28,7 @@ interface ChattyInterface
     /**
      * Setter injection for output into upgrade wizards
      *
-     * @param \Symfony\Component\Console\Output\OutputInterface $output
+     * @param OutputInterface $output
      */
     public function setOutput(OutputInterface $output): void;
 }
index 8283c2f..84f51b7 100644 (file)
@@ -1,4 +1,5 @@
 <?php
+
 namespace TYPO3\CMS\Install\Updates;
 
 /*
@@ -14,6 +15,7 @@ namespace TYPO3\CMS\Install\Updates;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Symfony\Component\Console\Output\OutputInterface;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -21,52 +23,91 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Remove all backend users starting with _cli_
  */
-class CommandLineBackendUserRemovalUpdate extends AbstractUpdate
+class CommandLineBackendUserRemovalUpdate implements UpgradeWizardInterface, ChattyInterface, RepeatableInterface, ConfirmableInterface
 {
     /**
-     * @var string
+     * @var OutputInterface
+     */
+    protected $output;
+
+    /**
+     * @var Confirmation
+     */
+    protected $confirmation;
+
+    public function __construct()
+    {
+        $this->confirmation = new Confirmation(
+            'Are you sure?',
+            'The following backend users will be removed: ' . implode(', ', $this->getUnneededCommandLineUsers()),
+            true
+        );
+    }
+
+    /**
+     * @return string Unique identifier of this updater
+     */
+    public function getIdentifier(): string
+    {
+        return 'commandLineBackendUserRemovalUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Remove unneeded CLI backend users';
+    }
+
+    /**
+     * @return string Longer description of this updater
      */
-    protected $title = 'Remove unneeded CLI backend users';
+    public function getDescription(): string
+    {
+        return 'The command line interface does not need to have custom _cli_* backend users anymore.'
+               . ' They can safely be deleted.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
         $needsExecution = false;
         $usersFound = $this->getUnneededCommandLineUsers();
         if (!empty($usersFound)) {
             $needsExecution = true;
-            $description = 'The command line interface does not need to have custom _cli_* backend users anymore. They can safely be deleted.';
         }
         return $needsExecution;
     }
 
     /**
-     * Shows information on the next step of the page
-     * @param string $formFieldNamePrefix
-     * @return string
+     * @param OutputInterface $output
      */
-    public function getUserInput($formFieldNamePrefix)
+    public function setOutput(OutputInterface $output): void
     {
-        $usersFound = $this->getUnneededCommandLineUsers();
-        return '<p>The following backend users will be deleted:</p><ul><li>' . implode('</li><li>', $usersFound) . '</li></ul>';
+        $this->output = $output;
+    }
+
+    /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class,
+        ];
     }
 
     /**
      * Performs the database update to set all be_users starting with _CLI_* to deleted
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $usersFound = $this->getUnneededCommandLineUsers();
         foreach ($usersFound as $userUid => $username) {
@@ -82,10 +123,11 @@ class CommandLineBackendUserRemovalUpdate extends AbstractUpdate
                 // value in $databaseQueries and not a statement placeholder
                 ->set('deleted', 1, false)
                 ->execute();
-            $databaseQueries[] = $queryBuilder->getSQL();
         }
-        $customMessage = '<p>The following backend users have been deleted:</p><ul><li>' . implode('</li><li>', $usersFound) . '</li></ul>';
-        $this->markWizardAsDone();
+        $this->output->writeln('The following backend users have been deleted:');
+        foreach ($usersFound as $user) {
+            $this->output->writeln('* ' . $user);
+        }
         return true;
     }
 
@@ -94,7 +136,7 @@ class CommandLineBackendUserRemovalUpdate extends AbstractUpdate
      *
      * @return array a list of uids
      */
-    protected function getUnneededCommandLineUsers()
+    protected function getUnneededCommandLineUsers(): array
     {
         $commandLineUsers = [];
 
@@ -108,7 +150,7 @@ class CommandLineBackendUserRemovalUpdate extends AbstractUpdate
             ->select('uid', 'username')
             ->from('be_users')
             ->where(
-                // Using query builder is complicated in this case. Get it straight, no user input is involved.
+            // Using query builder is complicated in this case. Get it straight, no user input is involved.
                 'LOWER(username) LIKE \'_cli_%\'',
                 $queryBuilder->expr()->neq(
                     'username',
@@ -123,4 +165,14 @@ class CommandLineBackendUserRemovalUpdate extends AbstractUpdate
 
         return $commandLineUsers;
     }
+
+    /**
+     * Return a confirmation message instance
+     *
+     * @return Confirmation
+     */
+    public function getConfirmation(): Confirmation
+    {
+        return $this->confirmation;
+    }
 }
index 345b092..5001991 100644 (file)
@@ -69,6 +69,7 @@ class DatabaseRowsUpdateWizard implements UpgradeWizardInterface, RepeatableInte
 
     /**
      * @return string Longer description of this updater
+     * @throws \RuntimeException
      */
     public function getDescription(): string
     {
index 9655b4f..12995ef 100644 (file)
@@ -31,7 +31,7 @@ class DatabaseUpdatedPrerequisite implements PrerequisiteInterface, ChattyInterf
      */
     protected $upgradeWizardsService;
     /**
-     * @var \Symfony\Component\Console\Output\OutputInterface
+     * @var OutputInterface
      */
     protected $output;
 
@@ -71,7 +71,7 @@ class DatabaseUpdatedPrerequisite implements PrerequisiteInterface, ChattyInterf
     }
 
     /**
-     * @param \Symfony\Component\Console\Output\OutputInterface $output
+     * @param OutputInterface $output
      */
     public function setOutput(OutputInterface $output): void
     {
index bf75a7a..804c0fa 100644 (file)
@@ -23,76 +23,40 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Contains the update class for filling the basic repository record of the extension manager
  */
-class ExtensionManagerTables extends AbstractUpdate
+class ExtensionManagerTables implements UpgradeWizardInterface, RepeatableInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Add the default Extension Manager database tables';
+    public function getIdentifier(): string
+    {
+        return 'extensionManagerTables';
+    }
 
     /**
-     * Gets all create, add and change queries from ext_tables.sql
-     *
-     * @return array
-     * @throws \BadFunctionCallException
-     * @throws \Doctrine\DBAL\DBALException
-     * @throws \Doctrine\DBAL\Schema\SchemaException
-     * @throws \InvalidArgumentException
-     * @throws \RuntimeException
-     * @throws \TYPO3\CMS\Core\Database\Schema\Exception\UnexpectedSignalReturnValueTypeException
-     * @throws \TYPO3\CMS\Core\Database\Schema\Exception\StatementException
-     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
-     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException
+     * @return string Title of this updater
      */
-    protected function getUpdateStatements()
+    public function getTitle(): string
     {
-        $updateStatements = [];
-
-        $emTableStatements = $this->getTableStatements();
-
-        if (count($emTableStatements)) {
-            $schemaMigrationService = GeneralUtility::makeInstance(SchemaMigrator::class);
-            $updateSuggestions = $schemaMigrationService->getUpdateSuggestions($emTableStatements);
-            $updateStatements = array_merge_recursive(...array_values($updateSuggestions));
-        }
-
-        return $updateStatements;
+        return 'Add the default Extension Manager database tables';
     }
 
     /**
-     * Get all CREATE TABLE statements from the ext_tables.sql file
-     *
-     * @return string[]
-     * @throws \BadFunctionCallException
-     * @throws \InvalidArgumentException
+     * @return string Longer description of this updater
      */
-    protected function getTableStatements(): array
+    public function getDescription(): string
     {
-        $rawDefinitions = file_get_contents(ExtensionManagementUtility::extPath('extensionmanager', 'ext_tables.sql'));
-        $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
-        return $sqlReader->getCreateTableStatementArray($rawDefinitions);
+        return 'Creates necessary database tables and adds static data for the Extension Manager.';
     }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
-     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotReturnException
-     * @throws \TYPO3\CMS\Extbase\SignalSlot\Exception\InvalidSlotException
-     * @throws \TYPO3\CMS\Core\Database\Schema\Exception\UnexpectedSignalReturnValueTypeException
-     * @throws \TYPO3\CMS\Core\Database\Schema\Exception\StatementException
-     * @throws \RuntimeException
-     * @throws \Doctrine\DBAL\Schema\SchemaException
-     * @throws \Doctrine\DBAL\DBALException
-     * @throws \BadFunctionCallException
-     * @throws \InvalidArgumentException
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
         $result = false;
-        $description = 'Creates necessary database tables and adds static data for the Extension Manager.';
-
         // First check necessary database update
         $updateStatements = array_filter($this->getUpdateStatements());
         if (count($updateStatements) === 0) {
@@ -107,22 +71,29 @@ class ExtensionManagerTables extends AbstractUpdate
         } else {
             $result = true;
         }
-
         return $result;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update.
      *
-     * @param array &$dbQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool Whether it worked (TRUE) or not (FALSE)
      */
-    public function performUpdate(array &$dbQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $result = true;
-        $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
 
+        $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
         $createTableStatements = $this->getTableStatements();
 
         // First perform all create, add and change queries
@@ -135,16 +106,37 @@ class ExtensionManagerTables extends AbstractUpdate
         );
 
         $insertStatements = $sqlReader->getInsertStatementArray($rawDefinitions);
-        $results = $schemaMigrationService->importStaticData($insertStatements);
+        $schemaMigrationService->importStaticData($insertStatements);
 
-        foreach ($results as $statement => $errorMessage) {
-            $dbQueries[] = $statement;
-            if ($errorMessage) {
-                $result = false;
-                $customMessage .= '<br /><br />SQL-ERROR: ' . htmlspecialchars($errorMessage);
-            }
+        return $result;
+    }
+
+    /**
+     * Gets all create, add and change queries from ext_tables.sql
+     *
+     * @return array
+     */
+    protected function getUpdateStatements()
+    {
+        $updateStatements = [];
+        $emTableStatements = $this->getTableStatements();
+        if (count($emTableStatements)) {
+            $schemaMigrationService = GeneralUtility::makeInstance(SchemaMigrator::class);
+            $updateSuggestions = $schemaMigrationService->getUpdateSuggestions($emTableStatements);
+            $updateStatements = array_merge_recursive(...array_values($updateSuggestions));
         }
+        return $updateStatements;
+    }
 
-        return $result;
+    /**
+     * Get all CREATE TABLE statements from the ext_tables.sql file
+     *
+     * @return string[]
+     */
+    protected function getTableStatements(): array
+    {
+        $rawDefinitions = file_get_contents(ExtensionManagementUtility::extPath('extensionmanager', 'ext_tables.sql'));
+        $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
+        return $sqlReader->getCreateTableStatementArray($rawDefinitions);
     }
 }
index e596eac..1bf26da 100644 (file)
@@ -1,6 +1,5 @@
 <?php
 declare(strict_types = 1);
-
 namespace TYPO3\CMS\Install\Updates;
 
 /*
@@ -26,50 +25,65 @@ use TYPO3\CMS\Core\Utility\MathUtility;
 /**
  * Migrate file references that are stored in a wrong way to correct scheme
  */
-class FileReferenceUpdate extends AbstractUpdate
+class FileReferenceUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Migrate file references that are stored in a wrong way to correct scheme';
+    public function getIdentifier(): string
+    {
+        return 'fileReferenceUpdate';
+    }
 
     /**
-     * Checks if an update is needed
-     *
-     * @param string &$description The description for the update
-     * @return bool Whether an update is needed (TRUE) or not (FALSE)
+     * @return string Title of this updater
      */
-    public function checkForUpdate(&$description)
+    public function getTitle(): string
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
+        return 'Migrate file references that are stored in a wrong way to correct scheme';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'File references were saved in a wrong way and references are not shown correctly in file list module.';
+    }
 
+    /**
+     * @return bool True if there are records to update
+     */
+    public function updateNecessary(): bool
+    {
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_refindex');
-        $count = $queryBuilder->count('hash')
+        return (bool)$queryBuilder->count('hash')
             ->from('sys_refindex')
             ->where(
                 $queryBuilder->expr()->eq('ref_table', $queryBuilder->createNamedParameter('_FILE', \PDO::PARAM_STR)),
                 $queryBuilder->expr()->eq('softref_key', $queryBuilder->createNamedParameter('typolink_tag', \PDO::PARAM_STR)),
                 $queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT))
             )
-            ->execute()->fetchColumn(0);
-
-        if ($count) {
-            $description = 'File references were saved in a wrong way and references aren\'t shown correctly in file list module.';
-        }
+            ->execute()
+            ->fetchColumn(0);
+    }
 
-        return (bool)$count;
+    /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
     }
 
     /**
-     * Performs the database update
+     * Performs the update
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_refindex');
         $queryBuilder = $connection->createQueryBuilder();
@@ -92,6 +106,7 @@ class FileReferenceUpdate extends AbstractUpdate
                         $fileReference = $fileObject->getUid();
                     }
                 } catch (Exception $e) {
+                    // Silently catch if there is no file object
                 }
             }
 
@@ -112,12 +127,9 @@ class FileReferenceUpdate extends AbstractUpdate
                 $updateQueryBuilder->set('deleted', 1);
             }
 
-            $databaseQueries[] = $updateQueryBuilder->getSQL();
             $updateQueryBuilder->execute();
         }
 
-        $this->markWizardAsDone();
-
         return true;
     }
 }
index 08ff40c..59df4c0 100644 (file)
@@ -20,24 +20,39 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Fill translation source field (l10n_source)
  */
-class FillTranslationSourceField extends AbstractUpdate
+class FillTranslationSourceField implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Fill translation source field (l10n_source)';
+    public function getIdentifier(): string
+    {
+        return 'fillTranslationSourceField';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Fill translation source field (l10n_source)';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'Fill translation source field (l10n_source) for tt_contents which have l18n_parent set.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getConnectionForTable('tt_content');
         $queryBuilder = $connection->createQueryBuilder();
@@ -48,22 +63,25 @@ class FillTranslationSourceField extends AbstractUpdate
                 $queryBuilder->expr()->gt('l18n_parent', $queryBuilder->createNamedParameter(0)),
                 $queryBuilder->expr()->eq('l10n_source', $queryBuilder->createNamedParameter(0))
             ));
-        $count = (int)$query->execute()->fetchColumn(0);
+        return (bool)$query->execute()->fetchColumn(0);
+    }
 
-        if ($count > 0) {
-            $description = 'Fill translation source field (l10n_source) for tt_contents which have l18n_parent set.';
-        }
-        return (bool)$count;
+    /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
     }
 
     /**
      * Performs the database update
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getConnectionForTable('tt_content');
@@ -74,10 +92,8 @@ class FillTranslationSourceField extends AbstractUpdate
             ->where($queryBuilder->expr()->andX(
                 $queryBuilder->expr()->gt('t.l18n_parent', $queryBuilder->createNamedParameter(0)),
                 $queryBuilder->expr()->eq('t.l10n_source', $queryBuilder->createNamedParameter(0))
-            ));
-        $databaseQueries[] = $queryBuilder->getSQL();
-        $queryBuilder->execute();
-        $this->markWizardAsDone();
+            ))
+            ->execute();
         return true;
     }
 }
index fc96f35..a61ceaf 100644 (file)
@@ -31,7 +31,7 @@ use TYPO3\CMS\Core\Utility\PathUtility;
  * Upgrade wizard which goes through all files referenced in fe_users::image
  * and creates sys_file records as well as sys_file_reference records for each hit.
  */
-class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwareInterface
+class FrontendUserImageUpdateWizard implements UpgradeWizardInterface, LoggerAwareInterface
 {
     use LoggerAwareTrait;
 
@@ -42,11 +42,6 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
     const RECORDS_PER_QUERY = 1000;
 
     /**
-     * @var string
-     */
-    protected $title = 'Migrate all file relations from fe_users.image to sys_file_references';
-
-    /**
      * @var ResourceStorage
      */
     protected $storage;
@@ -96,71 +91,89 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
     protected $recordOffset = [];
 
     /**
-     * Initialize the storage repository.
+     * @return string Unique identifier of this updater
      */
-    public function init()
+    public function getIdentifier(): string
     {
-        $storages = GeneralUtility::makeInstance(StorageRepository::class)->findAll();
-        $this->storage = $storages[0];
-        $this->registry = GeneralUtility::makeInstance(Registry::class);
-        $this->recordOffset = $this->registry->get($this->registryNamespace, 'recordOffset', []);
+        return 'frontendUserImageUpdateWizard';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate all file relations from fe_users.image to sys_file_references';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'This update wizard goes through all files that are referenced in the fe_users.image'
+            . ' field and adds the files to the FAL File Index. It also moves the files from'
+            . ' uploads/ to the fileadmin/_migrated/ path.';
     }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
-     *
      * @return bool TRUE if an update is needed, FALSE otherwise
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
-
-        $description = 'This update wizard goes through all files that are referenced in the fe_users.image field'
-            . ' and adds the files to the FAL File Index.<br />'
-            . 'It also moves the files from uploads/ to the fileadmin/_migrated/ path.';
-
         $this->init();
-
         return $this->recordOffset !== [];
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update.
      *
-     * @param array &$dbQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool TRUE on success, FALSE on error
      */
-    public function performUpdate(array &$dbQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
-        $customMessage = '';
         try {
             $this->init();
-
             if (!isset($this->recordOffset[$this->table])) {
                 $this->recordOffset[$this->table] = 0;
             }
-
             do {
                 $limit = $this->recordOffset[$this->table] . ',' . self::RECORDS_PER_QUERY;
-                $records = $this->getRecordsFromTable($limit, $dbQueries);
+                $records = $this->getRecordsFromTable($limit);
                 foreach ($records as $record) {
-                    $this->migrateField($record, $customMessage, $dbQueries);
+                    $this->migrateField($record);
                 }
                 $this->registry->set($this->registryNamespace, 'recordOffset', $this->recordOffset);
             } while (count($records) === self::RECORDS_PER_QUERY);
 
-            $this->markWizardAsDone();
             $this->registry->remove($this->registryNamespace, 'recordOffset');
         } catch (\Exception $e) {
-            $customMessage .= PHP_EOL . $e->getMessage();
+            // Silently catch db errors
         }
+        return true;
+    }
 
-        return empty($customMessage);
+    /**
+     * Initialize the storage repository.
+     */
+    protected function init()
+    {
+        $storages = GeneralUtility::makeInstance(StorageRepository::class)->findAll();
+        $this->storage = $storages[0];
+        $this->registry = GeneralUtility::makeInstance(Registry::class);
+        $this->recordOffset = $this->registry->get($this->registryNamespace, 'recordOffset', []);
     }
 
     /**
@@ -168,22 +181,18 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
      * and also not numeric (which means that it is migrated)
      *
      * @param int $limit Maximum number records to select
-     * @param array $dbQueries
-     *
      * @return array
      * @throws \RuntimeException
      */
-    protected function getRecordsFromTable($limit, &$dbQueries)
+    protected function getRecordsFromTable($limit)
     {
         $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
         $queryBuilder = $connectionPool->getQueryBuilderForTable($this->table);
-
         $queryBuilder->getRestrictions()
             ->removeAll()
             ->add(GeneralUtility::makeInstance(DeletedRestriction::class));
-
         try {
-            $result = $queryBuilder
+            return $queryBuilder
                 ->select('uid', 'pid', $this->fieldToMigrate)
                 ->from($this->table)
                 ->where(
@@ -200,11 +209,8 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
                 )
                 ->orderBy('uid')
                 ->setFirstResult($limit)
-                ->execute();
-
-            $dbQueries[] = $queryBuilder->getSQL();
-
-            return $result->fetchAll();
+                ->execute()
+                ->fetchAll();
         } catch (DBALException $e) {
             throw new \RuntimeException(
                 'Database query failed. Error was: ' . $e->getPrevious()->getMessage(),
@@ -217,12 +223,8 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
      * Migrates a single field.
      *
      * @param array $row
-     * @param string $customMessage
-     * @param array $dbQueries
-     *
-     * @throws \Exception
      */
-    protected function migrateField($row, &$customMessage, &$dbQueries)
+    protected function migrateField($row)
     {
         $fieldItems = GeneralUtility::trimExplode(',', $row[$this->fieldToMigrate], true);
         if (empty($fieldItems) || is_numeric($row[$this->fieldToMigrate])) {
@@ -281,7 +283,6 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
                     $file = $this->storage->getFile($this->targetPath . $item);
                     $fileUid = $file->getUid();
                 } catch (\InvalidArgumentException $e) {
-
                     // no file found, no reference can be set
                     $this->logger->notice(
                         'File ' . $this->sourcePath . $item . ' does not exist. Reference was not migrated.',
@@ -291,16 +292,6 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
                             'field' => $this->fieldToMigrate,
                         ]
                     );
-
-                    $format = 'File \'%s\' does not exist. Referencing field: %s.%d.%s. The reference was not migrated.';
-                    $message = sprintf(
-                        $format,
-                        $this->sourcePath . $item,
-                        $this->table,
-                        $row['uid'],
-                        $this->fieldToMigrate
-                    );
-                    $customMessage .= PHP_EOL . $message;
                     continue;
                 }
             }
@@ -321,7 +312,6 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
 
                 $queryBuilder = $connectionPool->getQueryBuilderForTable('sys_file_reference');
                 $queryBuilder->insert('sys_file_reference')->values($fields)->execute();
-                $dbQueries[] = str_replace(LF, ' ', $queryBuilder->getSQL());
                 ++$i;
             }
         }
@@ -336,7 +326,6 @@ class FrontendUserImageUpdateWizard extends AbstractUpdate implements LoggerAwar
                     $queryBuilder->createNamedParameter($row['uid'], \PDO::PARAM_INT)
                 )
             )->set($this->fieldToMigrate, $i)->execute();
-            $dbQueries[] = str_replace(LF, ' ', $queryBuilder->getSQL());
         } else {
             $this->recordOffset[$this->table]++;
         }
index fcf01f4..15ca149 100644 (file)
@@ -22,31 +22,43 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  * Update sys_language records to use the newly sorting column,
  * set default sorting from title
  */
-class LanguageSortingUpdate extends AbstractUpdate
+class LanguageSortingUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Update sorting of sys_language records';
+    public function getIdentifier(): string
+    {
+        return 'sysLanguageSorting';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Update sorting of sys_language records';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'The sys_language records have unsorted rows. '
+            . ' This upgrade wizard adds values depending on the language title';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
-     *
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description): bool
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            $this->markWizardAsDone();
-
-            return false;
-        }
-
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('sys_language');
-        $hasAffectedRows = (bool)$queryBuilder->count('uid')
+        return (bool)$queryBuilder->count('uid')
             ->from('sys_language')
             ->where(
                 $queryBuilder->expr()->eq('sorting', $queryBuilder->createNamedParameter(0, \PDO::PARAM_INT)),
@@ -54,24 +66,24 @@ class LanguageSortingUpdate extends AbstractUpdate
             )
             ->execute()
             ->fetchColumn(0);
+    }
 
-        if ($hasAffectedRows === true) {
-            $description = 'The sys_language records have unsorted rows. '
-                . ' This upgrade wizard adds values depending on the language title';
-        }
-
-        return $hasAffectedRows;
+    /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
     }
 
     /**
      * Performs the database update if the sorting field is 0 or null
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
-     *
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage): bool
+    public function executeUpdate(): bool
     {
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('sys_language');
@@ -93,13 +105,10 @@ class LanguageSortingUpdate extends AbstractUpdate
                         $queryBuilder->createNamedParameter($languageRecord['uid'], \PDO::PARAM_INT)
                     )
                 )
-                ->set('sorting', $sortCounter);
-            $databaseQueries[] = $queryBuilder->getSQL();
-            $queryBuilder->execute();
+                ->set('sorting', $sortCounter)
+                ->execute();
             $sortCounter *= 2;
         }
-        $this->markWizardAsDone();
-
         return true;
     }
 }
index 896afee..26ec752 100644 (file)
@@ -22,36 +22,46 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Merge sessions from old fe_session_data table into new structure from fe_sessions
  */
-class MigrateFeSessionDataUpdate extends AbstractUpdate
+class MigrateFeSessionDataUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Migrates existing fe_session_data into fe_sessions';
+    public function getIdentifier(): string
+    {
+        return 'migrateFeSessionDataUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrates existing fe_session_data into fe_sessions';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'With the new Session Framwework the session data is stored in fe_sessions.'
+            . ' To avoid that data is truncated, ensure the columns of fe_sessions have been updated.'
+            . ' This wizard migrates the existing data from fe_session_data into fe_sessions.'
+            . ' Existing entries in fe_sessions having an entry in fe_session_data are updated.'
+            . ' Entries in fe_session_data not found in fe_sessions are inserted with ses_anonymous = true';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string $description The description for the update
-     *
      * @return bool Whether an update is needed (true) or not (false)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
-
         if (!$this->checkIfTableExists('fe_session_data')) {
             return false;
         }
-
-        $description = 'With the new Session Framwework the session data is stored in fe_sessions.</p>'
-            . ' <b>To avoid that data is truncated, ensure the columns of fe_sessions have been updated.</b></p>'
-            . ' This wizard migrates the existing data from fe_session_data into fe_sessions.'
-            . ' Existing entries in fe_sessions having an entry in fe_session_data are updated.'
-            . ' Entries in fe_session_data not found in fe_sessions are inserted with ses_anonymous = true';
-
         // Check if there is data to migrate
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('fe_session_data');
@@ -65,14 +75,21 @@ class MigrateFeSessionDataUpdate extends AbstractUpdate
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Moves data from fe_session_data into fe_sessions with respect to ses_anonymous
      *
-     * @param array $databaseQueries Queries done in this update
-     * @param string $customMessage Custom messages
      * @return bool
-     * @throws \Doctrine\DBAL\DBALException
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('fe_sessions');
 
@@ -90,7 +107,6 @@ class MigrateFeSessionDataUpdate extends AbstractUpdate
                 )
             )
             ->execute();
-        $databaseQueries[] = $queryBuilder->getSQL();
 
         $updateQueryBuilder = $connection->createQueryBuilder();
         $updateQueryBuilder->update('fe_sessions')
@@ -101,7 +117,6 @@ class MigrateFeSessionDataUpdate extends AbstractUpdate
                 )
             )
             ->set('ses_data', $updateQueryBuilder->createPositionalParameter('', \PDO::PARAM_STR), false);
-        $databaseQueries[] = $updateQueryBuilder->getSQL();
         $updateStatement = $connection->prepare($updateQueryBuilder->getSQL());
 
         $connection->beginTransaction();
@@ -141,7 +156,6 @@ class MigrateFeSessionDataUpdate extends AbstractUpdate
             $connection->quoteIdentifier('ses_anonymous'),
             $selectSQL
         );
-        $databaseQueries[] = $insertSQL;
 
         try {
             $connection->beginTransaction();
@@ -152,7 +166,22 @@ class MigrateFeSessionDataUpdate extends AbstractUpdate
             throw $e;
         }
 
-        $this->markWizardAsDone();
         return true;
     }
+
+    /**
+     * Check if given table exists
+     *
+     * @param string $table
+     * @return bool
+     */
+    protected function checkIfTableExists($table): bool
+    {
+        $tableExists = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable($table)
+            ->getSchemaManager()
+            ->tablesExist([$table]);
+
+        return $tableExists;
+    }
 }
index 770d72f..89ec314 100644 (file)
@@ -20,24 +20,39 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Migrate "fluid_styled_content" static template location
  */
-class MigrateFscStaticTemplateUpdate extends AbstractUpdate
+class MigrateFscStaticTemplateUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Migrate "fluid_styled_content" static template location';
+    public function getIdentifier(): string
+    {
+        return 'migrateFscStaticTemplateUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate "fluid_styled_content" static template location';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'Static templates have been relocated to EXT:fluid_styled_content/Configuration/TypoScript/';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_template');
         $queryBuilder->getRestrictions()->removeAll();
         $elementCount = $queryBuilder->count('uid')
@@ -59,20 +74,25 @@ class MigrateFscStaticTemplateUpdate extends AbstractUpdate
                 )
             )
             ->execute()->fetchColumn(0);
-        if ($elementCount) {
-            $description = 'Static templates have been relocated to EXT:fluid_styled_content/Configuration/TypoScript/';
-        }
         return (bool)$elementCount;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_template');
         $queryBuilder = $connection->createQueryBuilder();
@@ -113,10 +133,8 @@ class MigrateFscStaticTemplateUpdate extends AbstractUpdate
                 ->set('include_static_file', $record['include_static_file'])
                 ->set('constants', $record['constants'])
                 ->set('config', $record['config']);
-            $databaseQueries[] = $queryBuilder->getSQL();
             $queryBuilder->execute();
         }
-        $this->markWizardAsDone();
         return true;
     }
 }
index 8b5c760..be1e959 100644 (file)
@@ -15,85 +15,109 @@ namespace TYPO3\CMS\Install\Updates;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Symfony\Component\Console\Output\OutputInterface;
 use TYPO3\CMS\Core\Configuration\ConfigurationManager;
 use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Install\Service\LoadTcaService;
 
 /**
- * Class MigratePagesLanguageOverlayUpdate
+ * Merge pages_language_overlay rows into pages table
  */
-class MigratePagesLanguageOverlayUpdate extends AbstractUpdate
+class MigratePagesLanguageOverlayUpdate implements UpgradeWizardInterface, ChattyInterface
 {
     /**
-     * The human-readable title of the upgrade wizard
-     *
-     * @var string
+     * @var OutputInterface
+     */
+    protected $output;
+
+    /**
+     * @return string Unique identifier of this updater
+     */
+    public function getIdentifier(): string
+    {
+        return 'pagesLanguageOverlay';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate content from pages_language_overlay to pages';
+    }
+
+    /**
+     * @return string Longer description of this updater
      */
-    protected $title = 'Migrate content from pages_language_overlay to pages';
+    public function getDescription(): string
+    {
+        return 'The table pages_language_overlay will be removed to align the translation '
+            . 'handling for pages with the rest of the core. This wizard transfers all data to the pages '
+            . 'table by creating new entries and linking them to the l10n parent. This might take a while, '
+            . 'because max. (amount of pages) x (active languages) new entries need be created.';
+    }
 
     /**
      * Checks whether updates are required.
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is required (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        $description = 'The table pages_language_overlay will be removed to align the translation ' .
-            'handling for pages with the rest of the core. This wizard transfers all data to the pages ' .
-            'table by creating new entries and linking them to the l10n parent. This might take a while, ' .
-            'because max. (amount of pages) x (active languages) new entries need be created.';
-
-        $updateNeeded = false;
-
         // Check if the database table even exists
-        if ($this->checkIfWizardIsRequired() && !$this->isWizardDone()) {
-            $updateNeeded = true;
+        if ($this->checkIfWizardIsRequired()) {
+            return true;
         }
+        return false;
+    }
 
-        return $updateNeeded;
+    /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
+     * Additional output if there are columns with mm config
+     *
+     * @param OutputInterface $output
+     */
+    public function setOutput(OutputInterface $output): void
+    {
+        $this->output = $output;
     }
 
     /**
-     * Shows information on the next step of the page
+     * Performs the update.
      *
-     * @param string $formFieldNamePrefix
-     * @return string
+     * @return bool Whether everything went smoothly or not
      */
-    public function getUserInput($formFieldNamePrefix)
+    public function executeUpdate(): bool
     {
-        $message = '';
         // Warn for TCA relation configurations which are not migrated.
-        if (isset($GLOBALS['TCA']['pages_language_overlay']['columns']) && is_array($GLOBALS['TCA']['pages_language_overlay']['columns'])) {
+        if (isset($GLOBALS['TCA']['pages_language_overlay']['columns'])
+            && is_array($GLOBALS['TCA']['pages_language_overlay']['columns'])
+        ) {
             foreach ($GLOBALS['TCA']['pages_language_overlay']['columns'] as $fieldName => $fieldConfiguration) {
                 if (isset($fieldConfiguration['config']['MM'])) {
-                    $message .= '<p>The pages_language_overlay field ' . $fieldName
+                    $this->output->writeln('The pages_language_overlay field ' . $fieldName
                         . ' with its MM relation configuration can not be migrated'
                         . ' automatically. Existing data relations to this field have'
-                        . ' to be migrated manually.</p>';
+                        . ' to be migrated manually.');
                 }
             }
         }
-        return $message;
-    }
 
-    /**
-     * Performs the accordant updates.
-     *
-     * @param array &$dbQueries Queries done in this update
-     * @param string &$customMessage Custom message
-     * @return bool Whether everything went smoothly or not
-     * @throws \InvalidArgumentException
-     */
-    public function performUpdate(array &$dbQueries, &$customMessage)
-    {
         // Ensure pages_language_overlay is still available in TCA
         GeneralUtility::makeInstance(LoadTcaService::class)->loadExtensionTablesWithoutMigration();
         $this->mergePagesLanguageOverlayIntoPages();
         $this->updateInlineRelations();
         $this->updateSysHistoryRelations();
-        $this->markWizardAsDone();
         $this->enableFeatureFlag();
         return true;
     }
@@ -252,7 +276,6 @@ class MigratePagesLanguageOverlayUpdate extends AbstractUpdate
      *
      * @param int $pageId
      * @return array
-     * @throws \InvalidArgumentException
      */
     protected function fetchDefaultLanguagePageRecord(int $pageId): array
     {
index 6b80054..db65ffe 100644 (file)
@@ -1,6 +1,5 @@
 <?php
 declare(strict_types = 1);
-
 namespace TYPO3\CMS\Install\Updates;
 
 /*
@@ -22,39 +21,47 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Merge URLs divided in pages.urltype and pages.url into pages.url
  */
-class MigrateUrlTypesInPagesUpdate extends AbstractUpdate
+class MigrateUrlTypesInPagesUpdate implements UpgradeWizardInterface
 {
+    private $databaseTables = ['pages', 'pages_language_overlay'];
+    private $urltypes = ['', 'http://', 'ftp://', 'mailto:', 'https://'];
+
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Migrate pages.urltype to pages.url';
+    public function getIdentifier(): string
+    {
+        return 'pagesUrltypeField';
+    }
 
-    private $databaseTables = ['pages', 'pages_language_overlay'];
-    private $urltypes = ['', 'http://', 'ftp://', 'mailto:', 'https://'];
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate pages.urltype to pages.url';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'The page property "URL Protocol" for external URLs has been merged into the URL itself.'
+            . ' The update wizard takes care of properly populating all existing pages and page translations.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string $description The description for the update
      * @return bool Whether an update is needed (true) or not (false)
-     * @throws \InvalidArgumentException
      */
-    public function checkForUpdate(&$description): bool
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
+        if (!$this->checkIfWizardIsRequired()) {
             return false;
         }
-
-        if ($this->checkIfWizardIsNotRequired()) {
-            $this->markWizardAsDone();
-            return false;
-        }
-
-        $description = '<p>The page property "URL Protocol" for external URLs has been merged into the URL itself.</p>
-The update wizard takes care of properly populating all existing pages and page translations.';
-
         $recordsToMigrate = 0;
-
         // Check if there is data to migrate
         foreach ($this->databaseTables as $databaseTable) {
             $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
@@ -73,46 +80,26 @@ The update wizard takes care of properly populating all existing pages and page
                 break;
             }
         }
-
         return $recordsToMigrate > 0;
     }
 
     /**
-     * Check each table if the column exists
-     *
-     * @return bool
-     * @throws \InvalidArgumentException
+     * @return string[] All new fields and tables must exist
      */
-    protected function checkIfWizardIsNotRequired(): bool
+    public function getPrerequisites(): array
     {
-        foreach ($this->databaseTables as $key => $databaseTable) {
-            $columns = GeneralUtility::makeInstance(ConnectionPool::class)
-                ->getConnectionForTable($databaseTable)
-                ->getSchemaManager()
-                ->listTableColumns($databaseTable);
-            if (!isset($columns['urltype'])) {
-                unset($this->databaseTables[$key]);
-            }
-        }
-
-        return count($this->databaseTables) === 0;
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
     }
 
     /**
      * Moves data from pages.urltype to pages.url
      *
-     * @param array $databaseQueries Queries done in this update
-     * @param string $customMessage Custom messages
      * @return bool
-     * @throws \InvalidArgumentException
-     * @throws \Doctrine\DBAL\DBALException
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage): bool
+    public function executeUpdate(): bool
     {
-        if ($this->checkIfWizardIsNotRequired()) {
-            $this->markWizardAsDone();
-            return false;
-        }
         foreach ($this->databaseTables as $databaseTable) {
             $connection = GeneralUtility::makeInstance(ConnectionPool::class)
                 ->getConnectionForTable($databaseTable);
@@ -128,8 +115,6 @@ The update wizard takes care of properly populating all existing pages and page
                 )
                 ->execute();
 
-            $databaseQueries[] = $queryBuilder->getSQL();
-
             while ($row = $statement->fetch()) {
                 $url = $this->urltypes[(int)$row['urltype']] . $row['url'];
                 $updateQueryBuilder = $connection->createQueryBuilder();
@@ -143,12 +128,28 @@ The update wizard takes care of properly populating all existing pages and page
                     )
                     ->set('url', $updateQueryBuilder->createNamedParameter($url), false)
                     ->set('urltype', 0);
-
-                $databaseQueries[] = $updateQueryBuilder->getSQL();
                 $updateQueryBuilder->execute();
             }
         }
-        $this->markWizardAsDone();
         return true;
     }
+
+    /**
+     * Check each table if the column exists
+     *
+     * @return bool
+     */
+    protected function checkIfWizardIsRequired(): bool
+    {
+        foreach ($this->databaseTables as $key => $databaseTable) {
+            $columns = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getConnectionForTable($databaseTable)
+                ->getSchemaManager()
+                ->listTableColumns($databaseTable);
+            if (!isset($columns['urltype'])) {
+                unset($this->databaseTables[$key]);
+            }
+        }
+        return count($this->databaseTables) > 0;
+    }
 }
index 91e63ef..dafd2a8 100644 (file)
@@ -29,54 +29,71 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  * - Check if realurl v1 (tx_realurl_pathcache) or v2 (tx_realurl_pathdata) has a page path, use that instead.
  * - If not -> generate the slug.
  */
-class PopulatePageSlugs extends AbstractUpdate
+class PopulatePageSlugs implements UpgradeWizardInterface
 {
+    protected $table = 'pages';
+
+    protected $fieldName = 'slug';
+
     /**
-     * The human-readable title of the upgrade wizard
-     *
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Introduce URL parts ("slugs") to all existing pages';
+    public function getIdentifier(): string
+    {
+        return 'pagesSlugs';
+    }
 
-    protected $table = 'pages';
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Introduce URL parts ("slugs") to all existing pages';
+    }
 
-    protected $fieldName = 'slug';
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'TYPO3 includes native URL handling. Every page record has its own speaking URL path'
+            . ' called "slug" which can be edited in TYPO3 Backend. However, it is necessary that all pages have'
+            . ' a URL pre-filled. This is done by evaluating the page title / navigation title and all of its rootline.';
+    }
 
     /**
      * Checks whether updates are required.
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is required (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description): bool
+    public function updateNecessary(): bool
     {
-        $description = 'TYPO3 includes native URL handling. Every page record has its own speaking URL path ' .
-            'called "slug" which can be edited in TYPO3 Backend. However, it is necessary that all pages have
-            a URL pre-filled. This is done by evaluating the page title / navigation title and all of its rootline.';
-
         $updateNeeded = false;
-
         // Check if the database table even exists
-        if ($this->checkIfWizardIsRequired() && !$this->isWizardDone()) {
+        if ($this->checkIfWizardIsRequired()) {
             $updateNeeded = true;
         }
-
         return $updateNeeded;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the accordant updates.
      *
-     * @param array &$dbQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool Whether everything went smoothly or not
-     * @throws \InvalidArgumentException
      */
-    public function performUpdate(array &$dbQueries, &$customMessage): bool
+    public function executeUpdate(): bool
     {
-        $results = $this->populateSlugs();
-        $customMessage .= implode('<br>', $results);
-        $this->markWizardAsDone();
+        $this->populateSlugs();
         return true;
     }
 
@@ -84,7 +101,7 @@ class PopulatePageSlugs extends AbstractUpdate
      * Fills the database table "pages" with slugs based on the page title and its configuration.
      * But also checks "legacy" functionality.
      */
-    protected function populateSlugs(): array
+    protected function populateSlugs()
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable($this->table);
         $queryBuilder = $connection->createQueryBuilder();
@@ -120,7 +137,6 @@ class PopulatePageSlugs extends AbstractUpdate
         $hasToBeUniqueInSite = in_array('uniqueInSite', $evalInfo, true);
         $hasToBeUniqueInPid = in_array('uniqueInPid', $evalInfo, true);
         $slugHelper = GeneralUtility::makeInstance(SlugHelper::class, $this->table, $this->fieldName, $fieldConfig);
-        $messages = [];
         while ($record = $statement->fetch()) {
             $recordId = (int)$record['uid'];
             $pid = (int)$record['pid'];
@@ -160,9 +176,7 @@ class PopulatePageSlugs extends AbstractUpdate
                 [$this->fieldName => $slug],
                 ['uid' => $recordId]
             );
-            $messages[] = 'Update record ' . $this->table . ':' . $recordId . ' with slug "' . htmlspecialchars($slug) . '"';
         }
-        return $messages;
     }
 
     /**
@@ -213,4 +227,20 @@ class PopulatePageSlugs extends AbstractUpdate
         }
         return $suggestedSlugs;
     }
+
+    /**
+     * Check if given table exists
+     *
+     * @param string $table
+     * @return bool
+     */
+    protected function checkIfTableExists($table)
+    {
+        $tableExists = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionForTable($table)
+            ->getSchemaManager()
+            ->tablesExist([$table]);
+
+        return $tableExists;
+    }
 }
index 01adfae..d2d0395 100644 (file)
@@ -110,7 +110,7 @@ class RedirectsExtensionUpdate extends AbstractDownloadExtensionUpdate
     public function executeUpdate(): bool
     {
         // Install the EXT:redirects extension if not happened yet
-        $installationSuccessful = $this->installExtension($this->extension->getKey());
+        $installationSuccessful = $this->installExtension($this->extension);
         if ($installationSuccessful) {
             // Migrate the database entries
             $this->migrateRedirectDomainsToSysRedirect();
index 0017e6d..9fb8ce9 100644 (file)
@@ -34,7 +34,7 @@ class ReferenceIndexUpdatedPrerequisite implements PrerequisiteInterface, Chatty
      */
     private $referenceIndex;
     /**
-     * @var \Symfony\Component\Console\Output\OutputInterface
+     * @var OutputInterface
      */
     protected $output;
 
@@ -83,7 +83,7 @@ class ReferenceIndexUpdatedPrerequisite implements PrerequisiteInterface, Chatty
     }
 
     /**
-     * @param \Symfony\Component\Console\Output\OutputInterface $output
+     * @param OutputInterface $output
      */
     public function setOutput(OutputInterface $output): void
     {
index d3f89ab..19d4a7d 100644 (file)
@@ -20,24 +20,41 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Migrate the field 'section_frame' for all content elements to 'frame_class'
  */
-class SectionFrameToFrameClassUpdate extends AbstractUpdate
+class SectionFrameToFrameClassUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Migrate the field "section_frame" for all content elements to "frame_class"';
+    public function getIdentifier(): string
+    {
+        return 'sectionFrameToFrameClassUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate the field "section_frame" for all content elements to "frame_class"';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'Section frames were used to control the wrapping of each content element in the frontend '
+            . 'output, stored as integers in the database. To get rid of a nessesary mapping of those values we '
+            . 'are now storing strings you can easily adjust that will simply passed to the rendering.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tt_content');
         $tableColumns = $connection->getSchemaManager()->listTableColumns('tt_content');
         // Only proceed if section_frame field still exists
@@ -51,23 +68,27 @@ class SectionFrameToFrameClassUpdate extends AbstractUpdate
             ->where(
                 $queryBuilder->expr()->gt('section_frame', 0)
             )
-            ->execute()->fetchColumn(0);
-        if ($elementCount) {
-            $description = 'Section frames were used to control the wrapping of each content element in the frontend '
-                . 'output, stored as integers in the database. To get rid of a nessesary mapping of those values we '
-                . 'are now storing strings you can easily adjust that will simply passed to the rendering.';
-        }
+            ->execute()
+            ->fetchColumn(0);
         return (bool)$elementCount;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tt_content');
         $queryBuilder = $connection->createQueryBuilder();
@@ -89,10 +110,8 @@ class SectionFrameToFrameClassUpdate extends AbstractUpdate
                 )
                 ->set('section_frame', 0, false)
                 ->set('frame_class', $this->mapSectionFrame($record['section_frame']));
-            $databaseQueries[] = $queryBuilder->getSQL();
             $queryBuilder->execute();
         }
-        $this->markWizardAsDone();
         return true;
     }
 
index 24f4c3d..3aabc6d 100644 (file)
@@ -23,34 +23,45 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Merge data stored in sys_log that belongs to sys_history
  */
-class SeparateSysHistoryFromSysLogUpdate extends AbstractUpdate
+class SeparateSysHistoryFromSysLogUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Migrates existing sys_log entries into sys_history';
+    public function getIdentifier(): string
+    {
+        return 'separateSysHistoryFromLog';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrates existing sys_log entries into sys_history';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'The history of changes of a record is now solely stored within sys_history.'
+            . ' Previous data within sys_log needs to be migrated into sys_history now.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string $description The description for the update
-     *
      * @return bool Whether an update is needed (true) or not (false)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
-
         // sys_log field has been removed, no need to do something.
         if (!$this->checkIfFieldInTableExists('sys_history', 'sys_log_uid')) {
             return false;
         }
 
-        $description = 'The history of changes of a record is now solely stored within sys_history. Previous data within sys_log needs to be'
-            . ' migrated into sys_history now.</p>';
-
         // Check if there is data to migrate
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getQueryBuilderForTable('sys_history');
@@ -65,15 +76,22 @@ class SeparateSysHistoryFromSysLogUpdate extends AbstractUpdate
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Moves data from sys_log into sys_history
      * where a reference is still there: sys_history.sys_log_uid > 0
      *
-     * @param array $databaseQueries Queries done in this update
-     * @param string $customMessage Custom messages
      * @return bool
-     * @throws \Doctrine\DBAL\DBALException
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         // update "modify" statements (= decoupling)
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('sys_history');
@@ -133,7 +151,6 @@ class SeparateSysHistoryFromSysLogUpdate extends AbstractUpdate
 
         foreach ($result as $row) {
             $logData = unserialize($row['log_data']);
-            /** @var RecordHistoryStore $store */
             $store = GeneralUtility::makeInstance(
                 RecordHistoryStore::class,
                 RecordHistoryStore::USER_BACKEND,
@@ -152,7 +169,6 @@ class SeparateSysHistoryFromSysLogUpdate extends AbstractUpdate
                     break;
             }
         }
-        $this->markWizardAsDone();
         return true;
     }
 
@@ -169,7 +185,6 @@ class SeparateSysHistoryFromSysLogUpdate extends AbstractUpdate
             ->getConnectionForTable($table)
             ->getSchemaManager()
             ->listTableColumns($table);
-
         return isset($tableColumns[$fieldName]);
     }
 }
index 3ee4cbf..e9c1364 100644 (file)
@@ -20,24 +20,41 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Split menu types into dedicated content elements
  */
-class SplitMenusUpdate extends AbstractUpdate
+class SplitMenusUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Split menu types into dedicated content elements';
+    public function getIdentifier(): string
+    {
+        return 'splitMenusUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Split menu types into dedicated content elements';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'Menus have been split into dedicated content elements to provide '
+            . 'a better maintainability and more easy to adjustable template with single '
+            . 'responsibility for the rendering.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tt_content');
         $tableColumns = $connection->getSchemaManager()->listTableColumns('tt_content');
         // Only proceed if menu_type field still exists
@@ -52,22 +69,25 @@ class SplitMenusUpdate extends AbstractUpdate
                 $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('menu', \PDO::PARAM_STR))
             )
             ->execute()->fetchColumn(0);
-        if ($elementCount) {
-            $description = 'Menus have been splitted into dedicated content elements to provide '
-                . 'a better maintainability and more easy to adjustable template with single '
-                . 'responsibility for the rendering.';
-        }
         return (bool)$elementCount;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tt_content');
         $queryBuilder = $connection->createQueryBuilder();
@@ -91,10 +111,8 @@ class SplitMenusUpdate extends AbstractUpdate
                     )
                 )
                 ->set('CType', $this->mapMenuTypes($record['menu_type']));
-            $databaseQueries[] = $queryBuilder->getSQL();
             $queryBuilder->execute();
         }
-        $this->markWizardAsDone();
         return true;
     }
 
index 7f0f688..0a4064b 100644 (file)
@@ -20,24 +20,42 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Update backend user setting startModule if set to "help_aboutmodules"
  */
-class StartModuleUpdate extends AbstractUpdate
+class StartModuleUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Update backend user setting "startModule"';
+    public function getIdentifier(): string
+    {
+        return 'startModuleUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Update backend user setting "startModule"';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'The backend user setting startModule is changed for the extensions about/aboutmodules.'
+            . ' Update all backend users that use ext:aboutmodules as startModule.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
         $queryBuilder->getRestrictions()->removeAll();
-
         $statement = $queryBuilder->select('uid', 'uc')->from('be_users')->execute();
         $needsExecution = false;
         while ($backendUser = $statement->fetch()) {
@@ -52,22 +70,26 @@ class StartModuleUpdate extends AbstractUpdate
                 }
             }
         }
-        if ($needsExecution) {
-            $description = 'The backend user setting startModule is changed for the extensions about/aboutmodules. Update all'
-                . ' backend users that use ext:aboutmodules as startModule.';
-        }
         return $needsExecution;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update if backend user's startmodule is
      * "help_aboutmodules" or "help_AboutmodulesAboutmodules"
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
         $queryBuilder->getRestrictions()->removeAll();
@@ -91,9 +113,8 @@ class StartModuleUpdate extends AbstractUpdate
                         )
                         // Manual quoting and false as third parameter to have the final
                         // value in $databaseQueries and not a statement placeholder
-                        ->set('uc', serialize($userConfig));
-                    $databaseQueries[] = $queryBuilder->getSQL();
-                    $queryBuilder->execute();
+                        ->set('uc', serialize($userConfig))
+                        ->execute();
                 }
             }
         }
index 4b47aa4..c863c75 100644 (file)
@@ -20,24 +20,39 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Migrate upload content element rendering from layout to uploads_type
  */
-class UploadContentElementUpdate extends AbstractUpdate
+class UploadContentElementUpdate implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = '[Optional] Migrate upload content element rendering from layout to uploads_type';
+    public function getIdentifier(): string
+    {
+        return 'uploadContentElementUpdate';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Migrate upload content element rendering from layout to uploads_type';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'Rendering type field has been streamlined with fluid_styled_content.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
-        if ($this->isWizardDone()) {
-            return false;
-        }
         $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');
         $queryBuilder->getRestrictions()->removeAll();
         $elementCount = $queryBuilder->count('uid')
@@ -46,21 +61,27 @@ class UploadContentElementUpdate extends AbstractUpdate
                 $queryBuilder->expr()->eq('CType', $queryBuilder->createNamedParameter('uploads', \PDO::PARAM_STR)),
                 $queryBuilder->expr()->in('layout', [1, 2])
             )
-            ->execute()->fetchColumn(0);
-        if ($elementCount) {
-            $description = 'Rendering type field has been streamlined with fluid_styled_content.';
-        }
+            ->execute()
+            ->fetchColumn(0);
         return (bool)$elementCount;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the database update
      *
-     * @param array &$databaseQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool
      */
-    public function performUpdate(array &$databaseQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $connection = GeneralUtility::makeInstance(ConnectionPool::class)->getConnectionForTable('tt_content');
         $queryBuilder = $connection->createQueryBuilder();
@@ -82,11 +103,9 @@ class UploadContentElementUpdate extends AbstractUpdate
                     )
                 )
                 ->set('layout', 0, false)
-                ->set('uploads_type', $record['layout']);
-            $databaseQueries[] = $queryBuilder->getSQL();
-            $queryBuilder->execute();
+                ->set('uploads_type', $record['layout'])
+                ->execute();
         }
-        $this->markWizardAsDone();
         return true;
     }
 }
index 8275033..212b717 100644 (file)
@@ -22,60 +22,79 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Move "wizard done" flags to system registry
  */
-class WizardDoneToRegistry extends AbstractUpdate
+class WizardDoneToRegistry implements UpgradeWizardInterface
 {
     /**
-     * @var string
+     * @return string Unique identifier of this updater
      */
-    protected $title = 'Move "wizard done" flags from LocalConfiguration.php to system registry';
+    public function getIdentifier(): string
+    {
+        return 'wizardDoneToRegistry';
+    }
+
+    /**
+     * @return string Title of this updater
+     */
+    public function getTitle(): string
+    {
+        return 'Move "wizard done" flags from LocalConfiguration.php to system registry';
+    }
+
+    /**
+     * @return string Longer description of this updater
+     */
+    public function getDescription(): string
+    {
+        return 'Moves all "wizard done" flags from LocalConfiguration.php to system registry.';
+    }
 
     /**
      * Checks if an update is needed
      *
-     * @param string &$description The description for the update
      * @return bool Whether an update is needed (TRUE) or not (FALSE)
      */
-    public function checkForUpdate(&$description)
+    public function updateNecessary(): bool
     {
         $result = false;
-        $description = 'Moves all "wizard done" flags from LocalConfiguration.php to system registry.';
-
         try {
-            $wizardsDone = GeneralUtility::makeInstance(ConfigurationManager::class)->getLocalConfigurationValueByPath('INSTALL/wizardDone');
+            $wizardsDone = GeneralUtility::makeInstance(ConfigurationManager::class)
+                ->getLocalConfigurationValueByPath('INSTALL/wizardDone');
             if (!empty($wizardsDone)) {
                 $result = true;
             }
         } catch (MissingArrayPathException $e) {
             // Result stays false with broken path
         }
-
         return $result;
     }
 
     /**
+     * @return string[] All new fields and tables must exist
+     */
+    public function getPrerequisites(): array
+    {
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
      * Performs the accordant updates.
      *
-     * @param array &$dbQueries Queries done in this update
-     * @param string &$customMessage Custom message
      * @return bool Whether everything went smoothly or not
      */
-    public function performUpdate(array &$dbQueries, &$customMessage)
+    public function executeUpdate(): bool
     {
         $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
         $registry = GeneralUtility::makeInstance(Registry::class);
         $wizardsDone = $configurationManager->getLocalConfigurationValueByPath('INSTALL/wizardDone');
         $configurationKeysToRemove = [];
-
         foreach ($wizardsDone as $wizardClassName => $value) {
             $registry->set('installUpdate', $wizardClassName, $value);
             $configurationKeysToRemove[] = 'INSTALL/wizardDone/' . $wizardClassName;
         }
-
         $configurationKeysToRemove[] = 'INSTALL/wizardDone';
-
         $configurationManager->removeLocalConfigurationKeysByPath($configurationKeysToRemove);
-
-        $this->markWizardAsDone();
         return true;
     }
 }
index 1dbb685..3dca2ba 100644 (file)
                <form>
                        <h4 class="t3js-upgradeWizards-input-title">{updateData.title}</h4>
                        <div class="t3js-upgradeWizards-input-html"></div>
-                       <div class="form-group">
-                               <div class="checkbox">
-                                       <label>
-                                               <input id="t3-install-showdatabasequeries" type="checkbox" name="install[values][showDatabaseQueries]" value="1" />
-                                               Show database queries performed
-                                       </label>
-                               </div>
-                       </div>
                        <button class="btn btn-warning t3js-upgradeWizards-input-perform" type="button">
                                Perform updates!
                        </button>
index 2ff9415..a090f91 100644 (file)
@@ -15,6 +15,7 @@ namespace TYPO3\CMS\Install\Tests\Functional\Updates;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Symfony\Component\Console\Output\OutputInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Install\Updates\CommandLineBackendUserRemovalUpdate;
 use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
@@ -32,9 +33,10 @@ class CommandLineBackendUserRemovalUpdateTest extends FunctionalTestCase
         $this->importCSVDataSet(GeneralUtility::getFileAbsFileName(
             'typo3/sysext/install/Tests/Functional/Updates/DataSet/CommandLineBackendUserRemovalBefore.csv'
         ));
-        $databaseQueries = [];
-        $customMessage = '';
-        (new CommandLineBackendUserRemovalUpdate())->performUpdate($databaseQueries, $customMessage);
+        $subject = new CommandLineBackendUserRemovalUpdate();
+        $outputProphecy = $this->prophesize(OutputInterface::class);
+        $subject->setOutput($outputProphecy->reveal());
+        $subject->executeUpdate();
         $this->assertCSVDataSet(GeneralUtility::getFileAbsFileName(
             'typo3/sysext/install/Tests/Functional/Updates/DataSet/CommandLineBackendUserRemovalAfter.csv'
         ));
index 93208bc..a113b15 100644 (file)
@@ -2,35 +2,35 @@
 defined('TYPO3_MODE') or die();
 
 // Do not delete this wizard. This makes sure new installations get the TER repository set in the database.
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\ExtensionManagerTables::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['extensionManagerTables']
     = \TYPO3\CMS\Install\Updates\ExtensionManagerTables::class;
 
 // TYPO3 CMS 8
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\WizardDoneToRegistry::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['wizardDoneToRegistry']
     = \TYPO3\CMS\Install\Updates\WizardDoneToRegistry::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\StartModuleUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['startModuleUpdate']
     = \TYPO3\CMS\Install\Updates\StartModuleUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\FrontendUserImageUpdateWizard::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['frontendUserImageUpdateWizard']
     = \TYPO3\CMS\Install\Updates\FrontendUserImageUpdateWizard::class;
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['databaseRowsUpdateWizard']
     = \TYPO3\CMS\Install\Updates\DatabaseRowsUpdateWizard::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\CommandLineBackendUserRemovalUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['commandLineBackendUserRemovalUpdate']
     = \TYPO3\CMS\Install\Updates\CommandLineBackendUserRemovalUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\FillTranslationSourceField::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['fillTranslationSourceField']
     = \TYPO3\CMS\Install\Updates\FillTranslationSourceField::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\SectionFrameToFrameClassUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['sectionFrameToFrameClassUpdate']
     = \TYPO3\CMS\Install\Updates\SectionFrameToFrameClassUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\SplitMenusUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['splitMenusUpdate']
     = \TYPO3\CMS\Install\Updates\SplitMenusUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\BulletContentElementUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['bulletContentElementUpdate']
     = \TYPO3\CMS\Install\Updates\BulletContentElementUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\UploadContentElementUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['uploadContentElementUpdate']
     = \TYPO3\CMS\Install\Updates\UploadContentElementUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\MigrateFscStaticTemplateUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['migrateFscStaticTemplateUpdate']
     = \TYPO3\CMS\Install\Updates\MigrateFscStaticTemplateUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\FileReferenceUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['fileReferenceUpdate']
     = \TYPO3\CMS\Install\Updates\FileReferenceUpdate::class;
-$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][\TYPO3\CMS\Install\Updates\MigrateFeSessionDataUpdate::class]
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['migrateFeSessionDataUpdate']
     = \TYPO3\CMS\Install\Updates\MigrateFeSessionDataUpdate::class;
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['compatibility7Extension']
     = \TYPO3\CMS\Install\Updates\Compatibility7ExtractionUpdate::class;