[BUGFIX] Make ext_update working 10/40610/2
authorMarkus Klein <markus.klein@typo3.org>
Wed, 24 Jun 2015 18:51:14 +0000 (20:51 +0200)
committerJigal van Hemert <jigal.van.hemert@typo3.org>
Thu, 25 Jun 2015 10:13:46 +0000 (12:13 +0200)
Running the actual update now works with all variants of ext_update
classes. Namespaced and non-namespaced.

Additionally we avoid autoloading at some places, since the composer
autoloader is too intelligent and finds the class from another ext.

Resolves: #67735
Releases: master, 6.2
Change-Id: Idec85d9b97cb67d862c0c8647e1490d146f27f45
Reviewed-on: http://review.typo3.org/40610
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
Tested-by: Jigal van Hemert <jigal.van.hemert@typo3.org>
Tested-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
typo3/sysext/extensionmanager/Classes/Utility/UpdateScriptUtility.php

index ffcbdc9..9766ee6 100644 (file)
@@ -13,7 +13,9 @@ namespace TYPO3\CMS\Extensionmanager\Utility;
  *
  * The TYPO3 project - inspiring people to share!
  */
+
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException;
 
 /**
  * Utility to find and execute class.ext_update.php scripts of extensions
@@ -29,22 +31,13 @@ class UpdateScriptUtility {
         * @return mixed NULL, if update is not available, else update script return
         */
        public function executeUpdateIfNeeded($extensionKey) {
-               $this->requireUpdateScript($extensionKey);
-               $scriptObject = new \ext_update;
+               $className = $this->requireUpdateScript($extensionKey);
+               $scriptObject = GeneralUtility::makeInstance($className);
+
                // old em always assumed the method exist, we do so too.
                // @TODO: Make this smart, let scripts implement interfaces
-               // @TODO: Enforce different update class script names per extension
-               // @TODO: With different class names it would be easily possible to check for updates in list view.
-               $accessReturnValue = $scriptObject->access();
-
-               $result = NULL;
-               if ($accessReturnValue === TRUE) {
-                       // @TODO: With current ext_update construct it is impossible
-                       // @TODO: to enforce some type of return
-                       $result = $scriptObject->main();
-               }
-
-               return $result;
+               // @TODO: With current ext_update construct it is impossible to enforce some type of return
+               return $scriptObject->access() ? $scriptObject->main() : NULL;
        }
 
        /**
@@ -53,86 +46,83 @@ class UpdateScriptUtility {
         * should be called before
         *
         * @param string $extensionKey
-        * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
+        * @return string Class name of update script
+        * @throws ExtensionManagerException
         */
        protected function requireUpdateScript($extensionKey) {
-               if (class_exists('ext_update')) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(
+               if (class_exists('ext_update', FALSE)) {
+                       throw new ExtensionManagerException(
                                'class ext_update for this run does already exist, requiring impossible',
                                1359748085
                        );
                }
 
-               $fileLocation = $this->getUpdateFileLocation($extensionKey);
-
-               if (!$this->checkUpdateScriptExists($extensionKey)) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(
+               $className = $this->determineUpdateClassName($extensionKey);
+               if ($className === '') {
+                       throw new ExtensionManagerException(
                                'Requested update script of extension does not exist',
                                1359747976
                        );
-
-               }
-               require $fileLocation;
-
-               if (!class_exists('ext_update')) {
-                       throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(
-                               'class.ext_update.php of extension did not declare ext_update class',
-                               1359748132
-                       );
                }
+               return $className;
        }
 
        /**
         * Checks if an update class file exists.
+        *
         * Does not check if some update is needed.
         *
         * @param string $extensionKey Extension key
-        * @return bool True, if there is some update script
-        * @throws \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException
+        * @return bool TRUE, if there is some update script and it needs to be executed
         */
        public function checkUpdateScriptExists($extensionKey) {
-               $updateScriptCanBeCalled = FALSE;
-               $updateScript = $this->getUpdateFileLocation($extensionKey);
-               if (file_exists($updateScript)) {
-                       // get script contents
-                       $scriptSourceCode = GeneralUtility::getUrl($updateScript);
-                       // check if it has a namespace
-                       if (!preg_match('/<\?php.*namespace\s+([^;]+);.*class/is', $scriptSourceCode, $matches)) {
-                               // if no, rename the class with a unique name
-                               $className = 'ext_update' . md5($extensionKey . $scriptSourceCode);
-                               $temporaryFileName = PATH_site . 'typo3temp/ExtensionManager/UpdateScripts/' . $className . '.php';
-                               if (!file_exists(GeneralUtility::getFileAbsFileName($temporaryFileName))) {
-                                       $scriptSourceCode = preg_replace('/^\s*class\s+ext_update\s+/m', 'class ' . $className . ' ', $scriptSourceCode);
-                                       GeneralUtility::writeFileToTypo3tempDir($temporaryFileName, $scriptSourceCode);
-                               }
-                               $updateScript = $temporaryFileName;
-                       } else {
-                               $className = $matches[1] . '\ext_update';
-                       }
-                       @include_once $updateScript;
-                       if (!class_exists($className)) {
-                               throw new \TYPO3\CMS\Extensionmanager\Exception\ExtensionManagerException(
-                                       sprintf('class.ext_update.php of extension "%s" did not declare ext_update class', $extensionKey),
-                                       1428176468
-                               );
-                       }
+               $className = $this->determineUpdateClassName($extensionKey);
+               if ($className !== '') {
                        $updater = GeneralUtility::makeInstance($className);
-                       $updateScriptCanBeCalled = $updater->access();
+                       return $updater->access();
                }
-               return $updateScriptCanBeCalled;
+               return FALSE;
        }
 
        /**
-        * Determines location of update file.
-        * Does not check if the file exists.
+        * Determine the real class name to use
         *
-        * @param string $extensionKey Extension key
-        * @return string Absolute path to possible update file of extension
+        * @param string $extensionKey
+        * @return string Returns the final class name if an update script is present, otherwise empty string
+        * @throws ExtensionManagerException If an update script is present but no ext_update class can be loaded
         */
-       protected function getUpdateFileLocation($extensionKey) {
-               return \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName(
+       protected function determineUpdateClassName($extensionKey) {
+               $updateScript = GeneralUtility::getFileAbsFileName(
                        'EXT:' . $extensionKey . '/class.ext_update.php',
                        FALSE
                );
+               if (!file_exists($updateScript)) {
+                       return '';
+               }
+
+               // get script contents
+               $scriptSourceCode = GeneralUtility::getUrl($updateScript);
+               // check if it has a namespace
+               if (!preg_match('/<\?php.*namespace\s+([^;]+);.*class/is', $scriptSourceCode, $matches)) {
+                       // if no, rename the class with a unique name
+                       $className = 'ext_update' . md5($extensionKey . $scriptSourceCode);
+                       $temporaryFileName = PATH_site . 'typo3temp/ExtensionManager/UpdateScripts/' . $className . '.php';
+                       if (!file_exists(GeneralUtility::getFileAbsFileName($temporaryFileName))) {
+                               $scriptSourceCode = preg_replace('/^\s*class\s+ext_update\s+/m', 'class ' . $className . ' ', $scriptSourceCode);
+                               GeneralUtility::writeFileToTypo3tempDir($temporaryFileName, $scriptSourceCode);
+                       }
+                       $updateScript = $temporaryFileName;
+               } else {
+                       $className = $matches[1] . '\ext_update';
+               }
+               @include_once $updateScript;
+               if (!class_exists($className, FALSE)) {
+                       throw new ExtensionManagerException(
+                               sprintf('class.ext_update.php of extension "%s" did not declare ext_update class', $extensionKey),
+                               1428176468
+                       );
+               }
+
+               return $className;
        }
 }