[FEATURE] Let the reports in the install module check for new versions 45/33745/16
authorWouter Wolters <typo3@wouterwolters.nl>
Wed, 12 Nov 2014 20:20:57 +0000 (21:20 +0100)
committerMarkus Klein <klein.t3@reelworx.at>
Fri, 19 Dec 2014 00:53:22 +0000 (01:53 +0100)
This patch modifies the reports of the install module. Now it behaves
similar to the install tool and issues an error or a warning status
when there is a new version available.

Currently this function only works for the current minor version
(e.g. 6.2.X). It will not notify about updates to e.g. 7.X.X. Besides
it does not take care about development versions at all.

Version information is downloaded from get.typo3.org. If this is not
possible, the old functionality is still working (which is printing out
the version information only with Status::NOTIFY.

With the version information it is checked if the current version is
up-to-date. If it is, the version is printed out with Status::OK. If not,
it checks if there is a security issue in the current version. If yes, the
status get severity Status::ERROR, otherwise Status::WARNING is used.

Resolves: #62444
Related: #62649
Releases: master
Change-Id: Ifdb62e3a4c34f700a73087271d7bff7daf6b8838
Reviewed-on: http://review.typo3.org/33745
Reviewed-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
Tested-by: Mathias Schreiber <mathias.schreiber@wmdb.de>
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
typo3/sysext/install/Classes/Report/InstallStatusReport.php
typo3/sysext/install/Resources/Private/Language/Report/locallang.xlf
typo3/sysext/reports/Classes/Report/Status/Typo3Status.php

index e61f1bb..2015966 100644 (file)
@@ -15,6 +15,9 @@ namespace TYPO3\CMS\Install\Report;
  */
 
 use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Reports\Status;
+use TYPO3\CMS\Install\Service\Exception;
 
 /**
  * Provides an installation status report
@@ -23,12 +26,12 @@ use TYPO3\CMS\Backend\Utility\BackendUtility;
  */
 class InstallStatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface {
 
-       protected $reportList = 'FileSystem,RemainingUpdates';
+       protected $reportList = 'FileSystem,RemainingUpdates,NewVersion';
 
        /**
         * Compiles a collection of system status checks as a status report.
         *
-        * @return array<\TYPO3\CMS\Reports\Status>
+        * @return Status[]
         */
        public function getStatus() {
                $reports = array();
@@ -47,7 +50,7 @@ class InstallStatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface
        protected function getFileSystemStatus() {
                $value = $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_writable');
                $message = '';
-               $severity = \TYPO3\CMS\Reports\Status::OK;
+               $severity = Status::OK;
                // Requirement level
                // -1 = not required, but if it exists may be writable or not
                //  0 = not required, if it exists the dir should be writable
@@ -74,23 +77,23 @@ class InstallStatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface
                foreach ($checkWritable as $relPath => $requirementLevel) {
                        if (!@is_dir((PATH_site . $relPath))) {
                                // If the directory is missing, try to create it
-                               \TYPO3\CMS\Core\Utility\GeneralUtility::mkdir(PATH_site . $relPath);
+                               GeneralUtility::mkdir(PATH_site . $relPath);
                        }
                        if (!@is_dir((PATH_site . $relPath))) {
                                if ($requirementLevel > 0) {
                                        // directory is required
                                        $value = $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_missingDirectory');
                                        $message .= sprintf($GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryDoesNotExistCouldNotCreate'), $relPath) . '<br />';
-                                       $severity = \TYPO3\CMS\Reports\Status::ERROR;
+                                       $severity = Status::ERROR;
                                } else {
                                        $message .= sprintf($GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryDoesNotExist'), $relPath);
                                        if ($requirementLevel == 0) {
                                                $message .= ' ' . $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryShouldAlsoBeWritable');
                                        }
                                        $message .= '<br />';
-                                       if ($severity < \TYPO3\CMS\Reports\Status::WARNING) {
+                                       if ($severity < Status::WARNING) {
                                                $value = $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_nonExistingDirectory');
-                                               $severity = \TYPO3\CMS\Reports\Status::WARNING;
+                                               $severity = Status::WARNING;
                                        }
                                }
                        } else {
@@ -98,21 +101,21 @@ class InstallStatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface
                                        switch ($requirementLevel) {
                                                case 0:
                                                        $message .= sprintf($GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryShouldBeWritable'), (PATH_site . $relPath)) . '<br />';
-                                                       if ($severity < \TYPO3\CMS\Reports\Status::WARNING) {
+                                                       if ($severity < Status::WARNING) {
                                                                $value = $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_recommendedWritableDirectory');
-                                                               $severity = \TYPO3\CMS\Reports\Status::WARNING;
+                                                               $severity = Status::WARNING;
                                                        }
                                                        break;
                                                case 2:
                                                        $value = $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_requiredWritableDirectory');
                                                        $message .= sprintf($GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_directoryMustBeWritable'), (PATH_site . $relPath)) . '<br />';
-                                                       $severity = \TYPO3\CMS\Reports\Status::ERROR;
+                                                       $severity = Status::ERROR;
                                                        break;
                                        }
                                }
                        }
                }
-               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_fileSystem'), $value, $message, $severity);
+               return GeneralUtility::makeInstance(Status::class, $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_fileSystem'), $value, $message, $severity);
        }
 
        /**
@@ -123,14 +126,57 @@ class InstallStatusReport implements \TYPO3\CMS\Reports\StatusProviderInterface
        protected function getRemainingUpdatesStatus() {
                $value = $GLOBALS['LANG']->getLL('status_updateComplete');
                $message = '';
-               $severity = \TYPO3\CMS\Reports\Status::OK;
-               if (!\TYPO3\CMS\Core\Utility\GeneralUtility::compat_version(TYPO3_branch)) {
+               $severity = Status::OK;
+               if (!GeneralUtility::compat_version(TYPO3_branch)) {
                        $value = $GLOBALS['LANG']->getLL('status_updateIncomplete');
-                       $severity = \TYPO3\CMS\Reports\Status::WARNING;
+                       $severity = Status::WARNING;
                        $url = BackendUtility::getModuleUrl('system_InstallInstall');
                        $message = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:warning.install_update'), '<a href="' . htmlspecialchars($url) . '">', '</a>');
                }
-               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_remainingUpdates'), $value, $message, $severity);
+               return GeneralUtility::makeInstance(Status::class, $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_remainingUpdates'), $value, $message, $severity);
+       }
+
+
+       /**
+        * Checks if there is a new minor TYPO3 version to update to
+        *
+        * @return \TYPO3\CMS\Reports\Status Represents whether there is a new version available online
+        */
+       protected function getNewVersionStatus() {
+               $objectManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Object\ObjectManager::class);
+               /** @var \TYPO3\CMS\Install\Service\CoreVersionService $coreVersionService */
+               $coreVersionService = $objectManager->get(\TYPO3\CMS\Install\Service\CoreVersionService::class);
+
+               // No updates for development versions
+               if (!$coreVersionService->isInstalledVersionAReleasedVersion()) {
+                       return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_isDevelopmentVersion'), Status::NOTICE);
+               }
+
+               // If fetching version matrix fails we can not do anything except print out the current version
+               try {
+                       $coreVersionService->updateVersionMatrix();
+               } catch (Exception\RemoteFetchException $remoteFetchException) {
+                       return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_remoteFetchException'), Status::NOTICE);
+               }
+
+               try {
+                       $isUpdateAvailable = $coreVersionService->isYoungerPatchReleaseAvailable();
+               } catch (Exception\CoreVersionServiceException $coreVersionServiceException) {
+                       return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, $GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_patchLevelNotFoundInReleaseMatrix'), Status::WARNING);
+               }
+
+               if (!$isUpdateAvailable) {
+                       // Everything is fine, working with the latest version
+                       return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, '', Status::OK);
+               }
+
+               // There is an update available
+               $newVersion = $coreVersionService->getYoungestPatchRelease();
+               if ($coreVersionService->isUpdateSecurityRelevant()) {
+                       return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, sprintf($GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_newVersionSecurityRelevant'), $newVersion), Status::ERROR);
+               } else {
+                       return GeneralUtility::makeInstance(Status::class, 'TYPO3', TYPO3_version, sprintf($GLOBALS['LANG']->sL('LLL:EXT:install/Resources/Private/Language/Report/locallang.xlf:status_newVersion'), $newVersion), Status::WARNING);
+               }
        }
 
 }
index 539cd50..ea12d31 100644 (file)
                        <trans-unit id="status_remainingUpdates" xml:space="preserve">
                                <source>Remaining updates</source>
                        </trans-unit>
+                       <trans-unit id="status_remoteFetchException" xml:space="preserve">
+                               <source>Could not fetch version matrix of TYPO3. Maybe this instance is blocked by a firewall?</source>
+                       </trans-unit>
+                       <trans-unit id="status_isDevelopmentVersion" xml:space="preserve">
+                               <source>This version of TYPO3 seems to be a development version. Thus no update information exists.</source>
+                       </trans-unit>
+                       <trans-unit id="status_patchLevelNotFoundInReleaseMatrix" xml:space="preserve">
+                               <source>It seems that this TYPO3 version has never been released. Thus no update information exists.</source>
+                       </trans-unit>
+                       <trans-unit id="status_newVersionSecurityRelevant" xml:space="preserve">
+                               <source>There is a new version of TYPO3 available. This update is security relevant. Please update to version %s</source>
+                       </trans-unit>
+                       <trans-unit id="status_newVersion" xml:space="preserve">
+                               <source>There is a new version of TYPO3 available. You can update to version %s</source>
+                       </trans-unit>
                </body>
        </file>
 </xliff>
index d72d24b..3496233 100644 (file)
@@ -13,6 +13,8 @@ namespace TYPO3\CMS\Reports\Report\Status;
  *
  * The TYPO3 project - inspiring people to share!
  */
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Reports\Status as ReportStatus;
 
 /**
  * Performs basic checks about the TYPO3 install
@@ -28,7 +30,6 @@ class Typo3Status implements \TYPO3\CMS\Reports\StatusProviderInterface {
         */
        public function getStatus() {
                $statuses = array(
-                       'Typo3Version' => $this->getTypo3VersionStatus(),
                        'oldXclassStatus' => $this->getOldXclassUsageStatus(),
                        'registeredXclass' => $this->getRegisteredXclassStatus(),
                );
@@ -36,15 +37,6 @@ class Typo3Status implements \TYPO3\CMS\Reports\StatusProviderInterface {
        }
 
        /**
-        * Simply gets the current TYPO3 version.
-        *
-        * @return \TYPO3\CMS\Reports\Status
-        */
-       protected function getTypo3VersionStatus() {
-               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Status::class, 'TYPO3', TYPO3_version, '', \TYPO3\CMS\Reports\Status::NOTICE);
-       }
-
-       /**
         * Check for usage of old way of implementing XCLASSes
         *
         * @return \TYPO3\CMS\Reports\Status
@@ -52,7 +44,7 @@ class Typo3Status implements \TYPO3\CMS\Reports\StatusProviderInterface {
        protected function getOldXclassUsageStatus() {
                $message = '';
                $value = $GLOBALS['LANG']->getLL('status_none');
-               $severity = \TYPO3\CMS\Reports\Status::OK;
+               $severity = ReportStatus::OK;
 
                $xclasses = array_merge(
                        (array)$GLOBALS['TYPO3_CONF_VARS']['BE']['XCLASS'],
@@ -64,11 +56,11 @@ class Typo3Status implements \TYPO3\CMS\Reports\StatusProviderInterface {
                        $value = sprintf($GLOBALS['LANG']->getLL('status_oldXclassUsageFound'), $numberOfXclasses);
                        $message = $GLOBALS['LANG']->getLL('status_oldXclassUsageFound_message') . '<br />';
                        $message .= '<ol><li>' . implode('</li><li>', $xclasses) . '</li></ol>';
-                       $severity = \TYPO3\CMS\Reports\Status::NOTICE;
+                       $severity = ReportStatus::NOTICE;
                }
 
-               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-                       \TYPO3\CMS\Reports\Status::class,
+               return GeneralUtility::makeInstance(
+                       ReportStatus::class,
                        $GLOBALS['LANG']->getLL('status_oldXclassUsage'),
                        $value,
                        $message,
@@ -84,7 +76,7 @@ class Typo3Status implements \TYPO3\CMS\Reports\StatusProviderInterface {
        protected function getRegisteredXclassStatus() {
                $message = '';
                $value = $GLOBALS['LANG']->getLL('status_none');
-               $severity = \TYPO3\CMS\Reports\Status::OK;
+               $severity = ReportStatus::OK;
 
                $xclassFoundArray = array();
                if (array_key_exists('Objects', $GLOBALS['TYPO3_CONF_VARS']['SYS'])) {
@@ -107,16 +99,15 @@ class Typo3Status implements \TYPO3\CMS\Reports\StatusProviderInterface {
                                $message .= '<li>' . $messageDetail . '</li>';
                        }
                        $message .= '</ol>';
-                       $severity = \TYPO3\CMS\Reports\Status::NOTICE;
+                       $severity = ReportStatus::NOTICE;
                }
 
-               return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
-                       \TYPO3\CMS\Reports\Status::class,
+               return GeneralUtility::makeInstance(
+                       ReportStatus::class,
                        $GLOBALS['LANG']->getLL('status_xclassUsage'),
                        $value,
                        $message,
                        $severity
                );
        }
-
 }