[TASK] Allow running AbstractUpdate wizards on CLI 70/58370/7
authorSusanne Moog <susanne.moog@typo3.org>
Fri, 21 Sep 2018 14:27:45 +0000 (16:27 +0200)
committerMarkus Klein <markus.klein@typo3.org>
Tue, 25 Sep 2018 21:02:21 +0000 (23:02 +0200)
To ease the update pain a compatibility layer for AbstractUpdate based
upgrade wizards has been implemented, that allows running "old" wizards
on CLI (enabling extension authors to support both v8 and v9 with one
wizard).

To get people to migrate to the new structure the methods in Abstract
Update have all been deprecated. As it is an abstract class this has
been done in all methods and the constructor as we cannot reliably know
which methods are overwritten.

Resolves: #86366
Relates: #86076
Releases: master
Change-Id: I3d4ba756ca37d82a918c1021c48b2f331e64f696
Reviewed-on: https://review.typo3.org/58370
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Deprecation-86366-MethodsInAbstractUpdate.rst [new file with mode: 0644]
typo3/sysext/install/Classes/Service/UpgradeWizardsService.php
typo3/sysext/install/Classes/Updates/AbstractUpdate.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/ClassNameMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86366-MethodsInAbstractUpdate.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-86366-MethodsInAbstractUpdate.rst
new file mode 100644 (file)
index 0000000..9fbd401
--- /dev/null
@@ -0,0 +1,54 @@
+.. include:: ../../Includes.txt
+
+===============================================
+Deprecation: #86366 - Methods in AbstractUpdate
+===============================================
+
+See :issue:`86366`
+
+Description
+===========
+
+To ease the update pain a compatibility layer for AbstractUpdate based
+upgrade wizards will be implemented, that allows running "old" wizards
+on CLI (enabling extension authors to support both v8 and v9 with one
+wizard).
+
+The following methods have been marked as deprecated and will be removed with TYPO3 v10:
+
+* AbstractUpdate::getTitle()
+* AbstractUpdate::setTitle()
+* AbstractUpdate::getIdentifier()
+* AbstractUpdate::setIdentifier()
+* AbstractUpdate::getDescription()
+* AbstractUpdate::executeUpdate()
+* AbstractUpdate::updateNecessary()
+* AbstractUpdate::getPrerequisites()
+* AbstractUpdate::setOutput()
+* AbstractUpdate::shouldRenderWizard()
+* AbstractUpdate::checkIfTableExists()
+* AbstractUpdate::installExtensions()
+* AbstractUpdate::markWizardAsDone()
+* AbstractUpdate::isWizardDone()
+
+The class itself has also been marked as deprecated, construction will trigger a PHP :php:`E_USER_DEPRECATED` error.
+
+Impact
+======
+
+Calling the mentioned methods through an extended class will trigger a PHP :php:`E_USER_DEPRECATED` error.
+
+All UpdateWizards extending AbstractUpdate gained cli capability since :issue:`86076`.
+
+Affected Installations
+======================
+
+Each instance with custom update wizards that extend AbstractUpdate.
+
+Migration
+=========
+
+Use the interfaces instead the abstract class to define the capabilities of the Upgrade Wizard class.
+See https://docs.typo3.org/typo3cms/extensions/core/latest/Changelog/9.4/Feature-86076-NewAPIForUpgradeWizards.html.
+
+.. index:: Backend, CLI, PHP-API, FullyScanned, ext:install
index f1e1aef..d7e20df 100644 (file)
@@ -28,7 +28,6 @@ use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
 use TYPO3\CMS\Core\Registry;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Install\Updates\AbstractUpdate;
 use TYPO3\CMS\Install\Updates\ChattyInterface;
 use TYPO3\CMS\Install\Updates\ConfirmableInterface;
 use TYPO3\CMS\Install\Updates\RepeatableInterface;
@@ -112,8 +111,7 @@ class UpgradeWizardsService
 
         $registry = GeneralUtility::makeInstance(Registry::class);
         $aWizardHasBeenMarkedUndone = false;
-        $wizardsDoneList = $this->listOfWizardsDone();
-        foreach ($wizardsDoneList as $wizard) {
+        foreach ($this->listOfWizardsDone() as $wizard) {
             if ($wizard['identifier'] === $identifier) {
                 $aWizardHasBeenMarkedUndone = true;
                 $registry->set('installUpdate', $wizard['class'], 0);
@@ -259,17 +257,12 @@ class UpgradeWizardsService
             if ($this->isWizardDone($identifier)) {
                 continue;
             }
-            /** @var AbstractUpdate $wizardInstance */
+            /** @var UpgradeWizardInterface $wizardInstance */
             $wizardInstance = GeneralUtility::makeInstance($class);
+            $explanation = '';
 
             // $explanation is changed by reference in Update objects!
-            // @todo deprecate once all wizards are migrated
-            $explanation = '';
             $shouldRenderWizard = false;
-            if (!($wizardInstance instanceof UpgradeWizardInterface) && $wizardInstance instanceof AbstractUpdate) {
-                $wizardInstance->checkForUpdate($explanation);
-                $shouldRenderWizard = $wizardInstance->shouldRenderWizard();
-            }
             if ($wizardInstance instanceof UpgradeWizardInterface) {
                 if ($wizardInstance instanceof ChattyInterface) {
                     $wizardInstance->setOutput($this->output);
@@ -305,6 +298,10 @@ class UpgradeWizardsService
         $wizardHtml = '';
         if (method_exists($updateObject, 'getUserInput')) {
             $wizardHtml = $updateObject->getUserInput('install[values][' . htmlspecialchars($identifier) . ']');
+            trigger_error(
+                'Deprecated since TYPO3 v9, will be removed in v10, use ConfirmableInterface directly.',
+                E_USER_DEPRECATED
+            );
         } elseif ($updateObject instanceof UpgradeWizardInterface && $updateObject instanceof ConfirmableInterface) {
             $wizardHtml = '
             <div class="panel panel-danger">
@@ -343,23 +340,28 @@ class UpgradeWizardsService
      * Execute a single update wizard
      *
      * @param string $identifier
-     * @param int $showDatabaseQueries
      * @return FlashMessageQueue
      * @throws \RuntimeException
      */
-    public function executeWizard(string $identifier, int $showDatabaseQueries = null): FlashMessageQueue
+    public function executeWizard(string $identifier): FlashMessageQueue
     {
         $this->assertIdentifierIsValid($identifier);
 
         $class = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update'][$identifier];
         $updateObject = GeneralUtility::makeInstance($class);
 
+        if ($updateObject instanceof ChattyInterface) {
+            $updateObject->setOutput($this->output);
+        }
         $messages = new FlashMessageQueue('install');
         // $wizardInputErrorMessage is given as reference to wizard object!
         $wizardInputErrorMessage = '';
         if (method_exists($updateObject, 'checkUserInput') &&
             !$updateObject->checkUserInput($wizardInputErrorMessage)) {
-            // @todo deprecate, unused
+            trigger_error(
+                'Deprecated since TYPO3 v9, will be removed in v10, use ConfirmableInterface.',
+                E_USER_DEPRECATED
+            );
             $messages->enqueue(
                 new FlashMessage(
                     $wizardInputErrorMessage ?: 'Something went wrong!',
@@ -368,16 +370,6 @@ class UpgradeWizardsService
                 )
             );
         } else {
-            if (!($updateObject instanceof UpgradeWizardInterface) && !method_exists($updateObject, 'performUpdate')) {
-                throw new \RuntimeException(
-                    'No performUpdate method in update wizard with identifier ' . $identifier,
-                    1371035200
-                );
-            }
-
-            // Both variables are used by reference in performUpdate()
-            $message = '';
-            $databaseQueries = [];
             if ($updateObject instanceof UpgradeWizardInterface) {
                 $requestParams = GeneralUtility::_GP('install');
                 if ($updateObject instanceof ConfirmableInterface
@@ -386,18 +378,13 @@ class UpgradeWizardsService
                         && empty($requestParams['values'][$updateObject->getIdentifier()]['install'])
                     )
                 ) {
+                    $this->output->writeln('No changes applied, marking wizard as done.');
                     // confirmation was set to "no"
                     $performResult = true;
                 } else {
                     // confirmation yes or non-confirmable
-                    if ($updateObject instanceof ChattyInterface) {
-                        $updateObject->setOutput($this->output);
-                    }
                     $performResult = $updateObject->executeUpdate();
                 }
-            } else {
-                // @todo deprecate
-                $performResult = $updateObject->performUpdate($databaseQueries, $message);
             }
 
             $stream = $this->output->getStream();
@@ -422,18 +409,6 @@ class UpgradeWizardsService
                     )
                 );
             }
-            if ($showDatabaseQueries) {
-                // @todo deprecate
-                foreach ($databaseQueries as $query) {
-                    $messages->enqueue(
-                        new FlashMessage(
-                            $query,
-                            '',
-                            FlashMessage::INFO
-                        )
-                    );
-                }
-            }
         }
         return $messages;
     }
index f6b7bcf..ce55f2c 100644 (file)
@@ -14,6 +14,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\Registry;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
@@ -21,9 +22,15 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
 /**
  * Generic class that every update wizard class inherits from.
  * Used by the update wizard in the install tool.
+ *
+ * @deprecated since TYPO3 v9, will be removed in v10
  */
-abstract class AbstractUpdate
+abstract class AbstractUpdate implements UpgradeWizardInterface, ChattyInterface
 {
+    public function __construct()
+    {
+        trigger_error('Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this), E_USER_DEPRECATED);
+    }
     /**
      * The human-readable title of the upgrade wizard
      *
@@ -46,12 +53,22 @@ abstract class AbstractUpdate
     public $userInput;
 
     /**
+     * @var OutputInterface
+     */
+    protected $output;
+
+    /**
      * Returns the title attribute
      *
+     * @deprecated Deprecated since TYPO3 v9
      * @return string The title of this update wizard
      */
     public function getTitle(): string
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         if ($this->title) {
             return $this->title;
         }
@@ -65,6 +82,10 @@ abstract class AbstractUpdate
      */
     public function setTitle($title)
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         $this->title = $title;
     }
 
@@ -75,7 +96,11 @@ abstract class AbstractUpdate
      */
     public function getIdentifier(): string
     {
-        return $this->identifier;
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
+        return $this->identifier ?? static::class;
     }
 
     /**
@@ -85,6 +110,10 @@ abstract class AbstractUpdate
      */
     public function setIdentifier($identifier)
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         $this->identifier = $identifier;
     }
 
@@ -98,6 +127,10 @@ abstract class AbstractUpdate
      */
     public function shouldRenderWizard()
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         $explanation = '';
         $result = $this->checkForUpdate($explanation);
         return (bool)$result === true;
@@ -111,6 +144,10 @@ abstract class AbstractUpdate
      */
     protected function checkIfTableExists($table)
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         $tableExists = GeneralUtility::makeInstance(ConnectionPool::class)
             ->getConnectionForTable($table)
             ->getSchemaManager()
@@ -144,6 +181,10 @@ abstract class AbstractUpdate
      */
     protected function installExtensions(array $extensionKeys)
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         /** @var \TYPO3\CMS\Extensionmanager\Utility\InstallUtility $installUtility */
         $installUtility = GeneralUtility::makeInstance(
             \TYPO3\CMS\Extensionmanager\Utility\InstallUtility::class
@@ -160,6 +201,10 @@ abstract class AbstractUpdate
      */
     protected function markWizardAsDone($confValue = 1)
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         GeneralUtility::makeInstance(Registry::class)->set('installUpdate', static::class, $confValue);
     }
 
@@ -170,7 +215,95 @@ abstract class AbstractUpdate
      */
     protected function isWizardDone()
     {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
         $wizardClassName = static::class;
         return GeneralUtility::makeInstance(Registry::class)->get('installUpdate', $wizardClassName, false);
     }
+
+    /**
+     * Return the description for this wizard
+     *
+     * @return string
+     */
+    public function getDescription(): string
+    {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
+        return '';
+    }
+
+    /**
+     * Execute the update
+     * Called when a wizard reports that an update is necessary
+     *
+     * @return bool
+     */
+    public function executeUpdate(): bool
+    {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
+        $queries = [];
+        $message = '';
+        $result = $this->performUpdate($queries, $message);
+        $this->output->write($message);
+        return $result;
+    }
+
+    /**
+     * Is an update necessary?
+     * Is used to determine whether a wizard needs to be run.
+     * Check if data for migration exists.
+     *
+     * @return bool
+     */
+    public function updateNecessary(): bool
+    {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
+        $description = '';
+        $result = $this->checkForUpdate($description);
+        $this->output->write($description);
+        return $result;
+    }
+
+    /**
+     * Returns an array of class names of Prerequisite classes
+     * This way a wizard can define dependencies like "database up-to-date" or
+     * "reference index updated"
+     *
+     * @return string[]
+     */
+    public function getPrerequisites(): array
+    {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
+        return [
+            DatabaseUpdatedPrerequisite::class
+        ];
+    }
+
+    /**
+     * Setter injection for output into upgrade wizards
+     *
+     * @param OutputInterface $output
+     */
+    public function setOutput(OutputInterface $output): void
+    {
+        trigger_error(
+            'Deprecated since TYPO3 v9, will be removed in v10, use UpgradeWizardInterface directly. affected class: ' . get_class($this),
+            E_USER_DEPRECATED
+        );
+        $this->output = $output;
+    }
 }
index e9cb64d..6d7860f 100644 (file)
@@ -944,4 +944,9 @@ return [
             'Deprecation-86225-ClassesBaseScriptClassAndAbstractFunctionModule.rst',
         ],
     ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate' => [
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
 ];
index b57452c..56ecdd2 100644 (file)
@@ -3425,4 +3425,102 @@ return [
             'Deprecation-85981-AnnotationFlushesCaches.rst'
         ],
     ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->getTitle' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->setTitle' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->getIdentifier' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->setIdentifier' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->getDescription' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->executeUpdate' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->updateNecessary' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->getPrerequisites' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->setOutput' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->shouldRenderWizard' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->checkIfTableExists' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->installExtensions' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->markWizardAsDone' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
+    'TYPO3\CMS\Install\Updates\AbstractUpdate->isWizardDone' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Deprecation-86366-MethodsInAbstractUpdate.rst'
+        ],
+    ],
 ];