[FEATURE] Uninstall broken ext in install tool 72/22972/3
authorSusanne Moog <typo3@susannemoog.de>
Thu, 8 Aug 2013 18:29:22 +0000 (20:29 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Thu, 8 Aug 2013 19:44:18 +0000 (21:44 +0200)
Adds buttons to uninstall incompatible extensions
to the install tool extension compatibility tester.
You may install extensions one-by-one or all at
once.

Change-Id: I717e127128f0f26e5b6711e0c1db04cf8d8cbfce
Resolves: #50940
Releases: 6.2
Reviewed-on: https://review.typo3.org/22972
Reviewed-by: Wouter Wolters
Tested-by: Wouter Wolters
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
typo3/sysext/install/Classes/Controller/Action/Ajax/ClearCache.php [new file with mode: 0644]
typo3/sysext/install/Classes/Controller/Action/Ajax/UninstallExtension.php [new file with mode: 0644]
typo3/sysext/install/Classes/Controller/AjaxController.php
typo3/sysext/install/Resources/Public/Javascript/Install.js

diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearCache.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/ClearCache.php
new file mode 100644 (file)
index 0000000..4874641
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+namespace TYPO3\CMS\Install\Controller\Action\Ajax;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Susanne Moog <typo3@susanne-moog.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Install\Controller\Action;
+use TYPO3\CMS\Core\Utility;
+
+/**
+ * Clear Cache
+ *
+ * This is an ajax wrapper for clearing the cache. Used for example
+ * after uninstalling an extension via ajax.
+ *
+ * @see \TYPO3\CMS\Install\Service\ClearCacheService
+ */
+class ClearCache extends Action\AbstractAction implements Action\ActionInterface {
+
+       /**
+        * Handle this action
+        *
+        * @return string content
+        */
+       public function handle() {
+               $this->initialize();
+               return $this->clearCache();
+       }
+
+       /**
+        * Wraps the cache service
+        *
+        * @return string
+        */
+       protected function clearCache() {
+               /** @var \TYPO3\CMS\Install\Service\ClearCacheService $clearCacheService */
+               $clearCacheService = $this->objectManager->get('TYPO3\\CMS\\Install\\Service\\ClearCacheService');
+               $clearCacheService->clearAll();
+               return 'OK';
+       }
+}
\ No newline at end of file
diff --git a/typo3/sysext/install/Classes/Controller/Action/Ajax/UninstallExtension.php b/typo3/sysext/install/Classes/Controller/Action/Ajax/UninstallExtension.php
new file mode 100644 (file)
index 0000000..7ee15cf
--- /dev/null
@@ -0,0 +1,76 @@
+<?php
+namespace TYPO3\CMS\Install\Controller\Action\Ajax;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Susanne Moog <typo3@susanne-moog.de>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+use TYPO3\CMS\Install\Controller\Action;
+use TYPO3\CMS\Core\Utility;
+
+/**
+ * Uninstall Extensions
+ *
+ * Used for uninstalling an extension (or multiple) via an ajax request.
+ * Warning! No dependency checking is done here, the extension is just removed
+ * from the extension list.
+ *
+ * If you use this class you have to take care of clearing the cache afterwards,
+ * it's not done here because for fully clearing the cache you need a reload
+ * to take care of changed cache configurations due to no longer installed extensions.
+ * Use the clearCache ajax action afterwards.
+ */
+class UninstallExtension extends Action\AbstractAction implements Action\ActionInterface {
+
+       /**
+        * Handle this action
+        *
+        * @return string content
+        */
+       public function handle() {
+               $this->initialize();
+               return $this->uninstallExtensions();
+       }
+
+       /**
+        * Uninstall one or multiple extensions
+        * Extension keys are read from get vars, more than one extension has to be comma separated
+        * Cache is cleared "hard" after uninstalling
+        *
+        * @return string
+        */
+       public function uninstallExtensions() {
+               $getVars = Utility\GeneralUtility::_GET('install');
+               if (isset($getVars['uninstallExtension']) && isset($getVars['uninstallExtension']['extensions'])) {
+                       $extensionsToUninstall = Utility\GeneralUtility::trimExplode(',', $getVars['uninstallExtension']['extensions']);
+                       foreach ($extensionsToUninstall as $extension) {
+                               if (Utility\ExtensionManagementUtility::isLoaded($extension)) {
+                                       Utility\ExtensionManagementUtility::unloadExtension($extension);
+                               }
+                       }
+               }
+               return 'OK';
+       }
+
+}
+
+?>
\ No newline at end of file
index 2182d40..d0ebb75 100644 (file)
@@ -42,7 +42,9 @@ class AjaxController extends AbstractController {
         * @var array List of valid action names that need authentication
         */
        protected $authenticationActions = array(
-               'extensionCompatibilityTester'
+               'extensionCompatibilityTester',
+               'uninstallExtension',
+               'clearCache'
        );
 
        /**
index 2195c00..d24ccd5 100644 (file)
@@ -78,17 +78,24 @@ $(document).ready(function() {
                }
        }).trigger('change');
 
-       $('#checkExtensions .typo3-message').hide();
-       $('#checkExtensions button').click(function(e) {
+       $('.typo3-message', '#checkExtensions').hide();
+       $('button', '#checkExtensions').click(function(e) {
                checkExtensionsCompatibility(true);
                e.preventDefault();
                return false;
        });
 });
 
+/**
+ * Checks extension compatibility by trying to load ext_tables and ext_localconf
+ * via ajax.
+ *
+ * @param force
+ */
 function checkExtensionsCompatibility(force) {
        var url = location.href + '&install[controller]=ajax&install[action]=extensionCompatibilityTester';
        if (force) {
+               clearCache();
                url += '&install[extensionCompatibilityTester][forceCheck]=1';
        } else {
                url += '&install[extensionCompatibilityTester][forceCheck]=0';
@@ -117,12 +124,47 @@ function checkExtensionsCompatibility(force) {
        });
 }
 
+/**
+ * Handles result of extension compatibility check.
+ * Displays uninstall buttons for non-compatible extensions.
+ */
 function handleCheckExtensionsSuccess() {
        $.ajax({
                url: $('#checkExtensions').data('protocolurl'),
+               cache: false,
                success: function(data) {
                        if (data) {
-                               $('.message-error .message-body', '#checkExtensions').html('The extension(s) ' + data + ' are not compatible. Please uninstall them and try again.');
+                               $('.message-error .message-body', '#checkExtensions').html(
+                                       'The following extensions are not compatible. Please uninstall them and try again. '
+                               );
+                               var extensions = data.split(',');
+                               var unloadButtonWrapper = $('<fieldset class="t3-install-form-submit"></fieldset>');
+                               for(var i=0; i<extensions.length; i++) {
+                                       var extension = extensions[i];
+                                       var unloadButton = $('<button />', {
+                                               text: 'Uninstall '+ $.trim(extension),
+                                               click: function(e) {
+                                                       uninstallExtension($.trim(extension));
+                                                       e.preventDefault();
+                                                       return false;
+                                               }
+                                       });
+                                       var fullButton = unloadButtonWrapper.append(unloadButton);
+                                       $('.message-error .message-body', '#checkExtensions').append(fullButton);
+                               }
+                               var unloadAllButton = $('<button />', {
+                                       text: 'Uninstall all incompatible extensions: '+ data,
+                                       click: function(e) {
+                                               uninstallExtension(data);
+                                               e.preventDefault();
+                                               return false;
+                                       }
+                               });
+                               unloadButtonWrapper.append('<hr />');
+                               var fullUnloadAllButton = unloadButtonWrapper.append(unloadAllButton);
+                               $('.message-error .message-body', '#checkExtensions').append(fullUnloadAllButton);
+
+
                                $('.message-error', '#checkExtensions').show();
                        } else {
                                $('.message-error', '#checkExtensions').hide();
@@ -144,4 +186,48 @@ function handleCheckExtensionsSuccess() {
  */
 function handleCheckExtensionsError() {
        checkExtensionsCompatibility(false);
+}
+
+/**
+ * Send an ajax request to uninstall an extension (or multiple extensions)
+ *
+ * @param extension string of extension(s) - may be comma separated
+ */
+function uninstallExtension(extension) {
+       var url = location.href + '&install[controller]=ajax&install[action]=uninstallExtension' +
+               '&install[uninstallExtension][extensions]=' + extension;
+       $.ajax({
+               url: url,
+               cache: false,
+               success: function(data) {
+                       if (data === 'OK') {
+                               checkExtensionsCompatibility(true);
+                       } else {
+                               if(data === 'unauthorized') {
+                                       location.reload();
+                               }
+                               // workaround for xdebug returning 200 OK on fatal errors
+                               if (data.substring(data.length - 2) === 'OK') {
+                                       checkExtensionsCompatibility(true);
+                               } else {
+                                       $('.message-error .message-body', '#checkExtensions').html(
+                                               'Something went wrong. Check failed.'
+                                       );
+                               }
+                       }
+               },
+               error: function(data) {
+                       handleCheckExtensionsError();
+               }
+       });
+}
+
+/**
+ * Ajax call to clear all caches.
+ */
+function clearCache() {
+       $.ajax({
+               url: location.href + '&install[controller]=ajax&install[action]=clearCache',
+               cache: false
+       });
 }
\ No newline at end of file