[BUGFIX] Allow overwrite when uploading an existing extension
authorKai Vogel <kai.vogel@speedprogs.de>
Wed, 3 Oct 2012 13:37:23 +0000 (15:37 +0200)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sun, 28 Oct 2012 16:23:48 +0000 (17:23 +0100)
This patch adds a checkbox to the upload form, which makes it possible
to overwrite the existing directory when uploading an extension
which is already available in the system.

Resolves: #41006
Releases: 6.0

Change-Id: Ib51a10a0e557060f0260e97ff8a9129f1c9f7eba
Reviewed-on: http://review.typo3.org/15257
Reviewed-by: Helmut Hummel
Tested-by: Helmut Hummel
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
typo3/sysext/extensionmanager/Classes/Controller/AbstractController.php
typo3/sysext/extensionmanager/Classes/Controller/DownloadController.php
typo3/sysext/extensionmanager/Classes/Controller/UploadExtensionFileController.php
typo3/sysext/extensionmanager/Classes/Utility/InstallUtility.php
typo3/sysext/extensionmanager/Resources/Private/Language/locallang.xlf
typo3/sysext/extensionmanager/Resources/Private/Templates/UploadExtensionFile/Extract.json
typo3/sysext/extensionmanager/Resources/Private/Templates/UploadExtensionFile/Form.html
typo3/sysext/extensionmanager/Resources/Public/JavaScript/upload.js

index ea1c8f9..561a252 100644 (file)
@@ -51,6 +51,16 @@ class AbstractController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionControl
                return $view;
        }
 
+       /**
+        * Translation shortcut
+        *
+        * @param $key
+        * @param NULL|array $arguments
+        * @return NULL|string
+        */
+       protected function translate($key, $arguments = NULL) {
+               return \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($key, 'extensionmanager', $arguments);
+       }
 }
 
 
index c1e05e3..cfc47ae 100644 (file)
@@ -215,15 +215,6 @@ class DownloadController extends \TYPO3\CMS\Extensionmanager\Controller\Abstract
                }
                $this->view->assign('updateComments', $updateComments)->assign('extensionKey', $extensionKey);
        }
-
-       /**
-        * @param $key
-        * @return NULL|string
-        */
-       protected function translate($key, $arguments = NULL) {
-               return \TYPO3\CMS\Extbase\Utility\LocalizationUtility::translate($key, 'extensionmanager', $arguments);
-       }
-
 }
 
 
index 4b58f32..85e2dcf 100644 (file)
@@ -87,25 +87,33 @@ class UploadExtensionFileController extends \TYPO3\CMS\Extensionmanager\Controll
        /**
         * Extract an uploaded file and install the matching extension
         *
+        * @param boolean $overwrite Overwrite existing extension if TRUE
         * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
         * @return void
         */
-       public function extractAction() {
-               $file = $_FILES['tx_extensionmanager_tools_extensionmanagerextensionmanager'];
-               $fileExtension = pathinfo($file['name']['extensionFile'], PATHINFO_EXTENSION);
-               $fileName = pathinfo($file['name']['extensionFile'], PATHINFO_BASENAME);
-               if (isset($file['name']['extensionFile']) && ($fileExtension !== 't3x' && $fileExtension !== 'zip')) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Wrong file format given.', 1342858853);
-               }
-               if (isset($file['tmp_name']['extensionFile'])) {
-                       $tempFile = \TYPO3\CMS\Core\Utility\GeneralUtility::upload_to_tempfile($file['tmp_name']['extensionFile']);
-               } else {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Creating temporary file failed.', 1342864339);
-               }
-               if ($fileExtension === 't3x') {
-                       $extensionData = $this->getExtensionFromT3xFile($tempFile);
-               } else {
-                       $extensionData = $this->getExtensionFromZipFile($tempFile, $fileName);
+       public function extractAction($overwrite = FALSE) {
+               try {
+                       $file = $_FILES['tx_extensionmanager_tools_extensionmanagerextensionmanager'];
+                       $fileExtension = pathinfo($file['name']['extensionFile'], PATHINFO_EXTENSION);
+                       $fileName = pathinfo($file['name']['extensionFile'], PATHINFO_BASENAME);
+                       if (empty($file['name']['extensionFile'])) {
+                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('No file given.', 1342858852);
+                       }
+                       if ($fileExtension !== 't3x' && $fileExtension !== 'zip') {
+                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Wrong file format given.', 1342858853);
+                       }
+                       if (!empty($file['tmp_name']['extensionFile'])) {
+                               $tempFile = \TYPO3\CMS\Core\Utility\GeneralUtility::upload_to_tempfile($file['tmp_name']['extensionFile']);
+                       } else {
+                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Creating temporary file failed.', 1342864339);
+                       }
+                       if ($fileExtension === 't3x') {
+                               $extensionData = $this->getExtensionFromT3xFile($tempFile, $overwrite);
+                       } else {
+                               $extensionData = $this->getExtensionFromZipFile($tempFile, $fileName, $overwrite);
+                       }
+               } catch (\Exception $exception) {
+                       $this->view->assign('error', $exception->getMessage());
                }
                $this->view->assign('extensionKey', $extensionData['extKey']);
        }
@@ -113,22 +121,25 @@ class UploadExtensionFileController extends \TYPO3\CMS\Extensionmanager\Controll
        /**
         * Extracts a given t3x file and installs the extension
         *
-        * @param string $file
+        * @param string $file Path to uploaded file
+        * @param boolean $overwrite Overwrite existing extension if TRUE
         * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
         * @return array
         */
-       protected function getExtensionFromT3xFile($file) {
+       protected function getExtensionFromT3xFile($file, $overwrite = FALSE) {
                $fileContent = \TYPO3\CMS\Core\Utility\GeneralUtility::getUrl($file);
                if (!$fileContent) {
                        throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('File had no or wrong content.', 1342859339);
                }
                $extensionData = $this->terUtility->decodeExchangeData($fileContent);
-               if ($extensionData['extKey']) {
-                       $this->fileHandlingUtility->unpackExtensionFromExtensionDataArray($extensionData);
-                       $this->installUtility->install($extensionData['extKey']);
-               } else {
+               if (empty($extensionData['extKey'])) {
                        throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Decoding the file went wrong. No extension key found', 1342864309);
                }
+               if (!$overwrite && $this->installUtility->isAvailable($extensionData['extKey'])) {
+                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException($this->translate('extensionList.overwritingDisabled'), 1342864310);
+               }
+               $this->fileHandlingUtility->unpackExtensionFromExtensionDataArray($extensionData);
+               $this->installUtility->install($extensionData['extKey']);
                return $extensionData;
        }
 
@@ -138,15 +149,21 @@ class UploadExtensionFileController extends \TYPO3\CMS\Extensionmanager\Controll
         * we have to use the file name to get that information
         * filename format is expected to be extensionkey_version.zip
         *
-        * @param string $file path to uploaded file
-        * @param string $fileName filename (basename) of uploaded file
+        * @param string $file Path to uploaded file
+        * @param string $fileName Filename (basename) of uploaded file
+        * @param boolean $overwrite Overwrite existing extension if TRUE
         * @return array
         */
-       protected function getExtensionFromZipFile($file, $fileName) {
-               $fileNameParts = \TYPO3\CMS\Core\Utility\GeneralUtility::revExplode('_', $fileName, 2);
-               $this->fileHandlingUtility->unzipExtensionFromFile($file, $fileNameParts[0]);
-               $this->installUtility->install($fileNameParts[0]);
-               return array('extKey' => $fileNameParts[0]);
+       protected function getExtensionFromZipFile($file, $fileName, $overwrite = FALSE) {
+                       // Remove version and ending from filename to determine extension key
+               $extensionKey = preg_replace('/_(\d+)(\.|\-)(\d+)(\.|\-)(\d+)/i', '', strtolower($fileName));
+               $extensionKey = substr($extensionKey, 0, strrpos($extensionKey, '.'));
+               if (!$overwrite && $this->installUtility->isAvailable($extensionKey)) {
+                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException('Extension is already available and overwriting is disabled.', 1342864311);
+               }
+               $this->fileHandlingUtility->unzipExtensionFromFile($file, $extensionKey);
+               $this->installUtility->install($extensionKey);
+               return array('extKey' => $extensionKey);
        }
 
 }
index b81a384..1df0335 100644 (file)
@@ -137,6 +137,28 @@ class InstallUtility implements \TYPO3\CMS\Core\SingletonInterface {
                $this->dependencyUtility = $this->objectManager->get('TYPO3\\CMS\\Extensionmanager\\Utility\\DependencyUtility');
        }
 
+       /**
+        * Helper function to install an extension
+        * also processes db updates and clears the cache if the extension asks for it
+        *
+        * @param string $extensionKey
+        * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
+        * @return void
+        */
+       public function install($extensionKey) {
+               $extension = $this->enrichExtensionWithDetails($extensionKey);
+               $this->processDatabaseUpdates($extension);
+               $this->ensureConfiguredDirectoriesExist($extension);
+               if ($extension['clearcacheonload']) {
+                       $GLOBALS['typo3CacheManager']->flushCaches();
+               }
+               if (!$this->isLoaded($extensionKey)) {
+                       $this->loadExtension($extensionKey);
+               }
+               $this->reloadCaches();
+               $this->saveDefaultConfiguration($extension['key']);
+       }
+
        /**
         * Helper function to uninstall an extension
         *
@@ -154,42 +176,44 @@ class InstallUtility implements \TYPO3\CMS\Core\SingletonInterface {
        }
 
        /**
-        * Wrapper function for unloading extensions
+        * Wrapper function to check for loaded extensions
         *
         * @param string $extensionKey
+        * @return boolean TRUE if extension is loaded
         */
-       protected function unloadExtension($extensionKey) {
-               \TYPO3\CMS\Core\Extension\ExtensionManager::unloadExtension($extensionKey);
+       public function isLoaded($extensionKey) {
+               return \TYPO3\CMS\Core\Extension\ExtensionManager::isLoaded($extensionKey);
        }
 
        /**
-        * Helper function to install an extension
-        * also processes db updates and clears the cache if the extension asks for it
+        * Wrapper function for loading extensions
         *
         * @param string $extensionKey
-        * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
         * @return void
         */
-       public function install($extensionKey) {
-               $extension = $this->enrichExtensionWithDetails($extensionKey);
-               $this->processDatabaseUpdates($extension);
-               $this->ensureConfiguredDirectoriesExist($extension);
-               if ($extension['clearcacheonload']) {
-                       $GLOBALS['typo3CacheManager']->flushCaches();
-               }
-               $this->loadExtension($extensionKey);
-               $this->reloadCaches();
-               $this->saveDefaultConfiguration($extension['key']);
+       protected function loadExtension($extensionKey) {
+               \TYPO3\CMS\Core\Extension\ExtensionManager::loadExtension($extensionKey);
        }
 
        /**
-        * Wrapper function for loading extensions
+        * Wrapper function for unloading extensions
         *
         * @param string $extensionKey
         * @return void
         */
-       protected function loadExtension($extensionKey) {
-               \TYPO3\CMS\Core\Extension\ExtensionManager::loadExtension($extensionKey);
+       protected function unloadExtension($extensionKey) {
+               \TYPO3\CMS\Core\Extension\ExtensionManager::unloadExtension($extensionKey);
+       }
+
+       /**
+        * Checks if an extension is available in the system
+        *
+        * @param $extensionKey
+        * @return boolean
+        */
+       public function isAvailable($extensionKey) {
+               $availableExtensions = $this->listUtility->getAvailableExtensions();
+               return array_key_exists($extensionKey, $availableExtensions);
        }
 
        /**
index 0294ed1..0efeff3 100644 (file)
                        <trans-unit id="extensionList.uploadExtension" xml:space="preserve">
                                <source>Upload Extension .t3x/.zip</source>
                        </trans-unit>
+                       <trans-unit id="extensionList.overwriteExtension" xml:space="preserve">
+                               <source>Overwrite</source>
+                       </trans-unit>
+                       <trans-unit id="extensionList.overwritingDisabled" xml:space="preserve">
+                               <source>Extension is already available and overwriting was not enabled</source>
+                       </trans-unit>
                        <trans-unit id="extensionList.loading" xml:space="preserve">
                                <source>Loading form...</source>
                        </trans-unit>
index fb034db..3e011c8 100644 (file)
@@ -1,2 +1,2 @@
 {namespace em=TYPO3\CMS\Extensionmanager\ViewHelpers}
-<em:format.jsonEncode additionalAttributes="{success:'true', extension:extensionKey}" />
\ No newline at end of file
+<em:format.jsonEncode additionalAttributes="{success:'true', extension:extensionKey, error:error}" />
\ No newline at end of file
index 80a5c31..cda6a6e 100644 (file)
@@ -1,6 +1,7 @@
-<f:form enctype="multipart/form-data" method="post" controller="UploadExtensionFile" action="extract" format="json" additionalAttributes="{target:'typo3-extensionmanager-upload-target'}">
+<f:form enctype="multipart/form-data" id="extensionUploadForm" method="post" controller="UploadExtensionFile" action="extract" format="json" additionalAttributes="{target:'typo3-extensionmanager-upload-target'}">
        <f:translate key="uploadTemplate.extensionLabel" />:
-       <f:form.upload name="extensionFile"/>
-       <f:form.submit value="{f:translate(key:'uploadTemplate.uploadButton')}" id="extensionUpload"/>
+       <f:form.upload name="extensionFile" />
+       <f:form.checkbox name="overwrite" id="extensionOverwrite" value="1" /><label for="extensionOverwrite">{f:translate(key:'extensionList.overwriteExtension')}</label>
+       <f:form.submit value="{f:translate(key:'uploadTemplate.uploadButton')}" id="extensionUpload" />
        <iframe id="typo3-extensionmanager-upload-target" name="typo3-extensionmanager-upload-target" style="display: none;"></iframe>
-</f:form>
\ No newline at end of file
+</f:form>
index 4750d6c..ee747e8 100644 (file)
@@ -1,34 +1,36 @@
 // IIFE for faster access to $ and save $ use
 (function ($) {
 
-       $(document).ready(function() {
-               $('.t3-icon-edit-upload').parent().not('.transformed').each(function () {
-                       $(this).data('href', $(this).attr('href'));
-                       $(this).attr('href', '#');
+       $(function() {
+               // Show upload form
+               $('.t3-icon-edit-upload').parent().not('.transformed').on('click', function(event) {
+                       event.preventDefault();
                        $(this).addClass('transformed');
-                       $(this).click(function () {
-                               $('.uploadForm').show();
-                               $.ajax({
-                                       url:$(this).data('href'),
-                                       dataType:'html',
-                                       success:function (data) {
-                                               $('.uploadForm').html(data);
-                                               handleUploadForm();
-                                       }
-                               });
+                       $('.uploadForm').show();
+                       $.ajax({
+                               url: $(this).attr('href'),
+                               dataType: 'html',
+                               success: function (data) {
+                                       $('.uploadForm').html(data);
+                                       handleUploadForm();
+                               }
                        });
                });
-       });
-
-       function handleUploadForm() {
-               $('#typo3-extensionmanager-upload-target').on('load', function() {
-                       var ret = frames['typo3-extensionmanager-upload-target'].document.getElementsByTagName("body")[0].innerHTML;
-                       var data = eval("("+ret+")");
-                       if (data.success) {
-                               TYPO3.Flashmessage.display(TYPO3.Severity.information, TYPO3.l10n.localize('extensionList.uploadFlashMessage.title'), TYPO3.l10n.localize('extensionList.uploadFlashMessage.message').replace(/\{0\}/g, data.extension), 15);
-                               location.reload();
-                       }
-               });
-       }
 
+               function handleUploadForm() {
+                       // Handle form submit response
+                       $('#typo3-extensionmanager-upload-target').on('load', function(event) {
+                               var html = $.trim($(this).contents().find('body').html());
+                               if (html[0] === '{') {
+                                       var data = $.parseJSON(html);
+                                       if (data.error) {
+                                               TYPO3.Flashmessage.display(TYPO3.Severity.error, 'Extension Upload failed', data.error, 5);
+                                       } else if (data.success) {
+                                               TYPO3.Flashmessage.display(TYPO3.Severity.information, TYPO3.l10n.localize('extensionList.uploadFlashMessage.title'), TYPO3.l10n.localize('extensionList.uploadFlashMessage.message').replace(/\{0\}/g, data.extension), 15);
+                                               location.reload();
+                                       }
+                               }
+                       });
+               }
+       });
 }(jQuery));