[BUGFIX] Introduce failsafe view in install tool 67/27067/11
authorHelmut Hummel <helmut.hummel@typo3.org>
Thu, 6 Mar 2014 08:40:41 +0000 (09:40 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Sat, 8 Mar 2014 20:04:20 +0000 (21:04 +0100)
The installer does not work, if doc comment reflection
is broken, so we need to make the first install step
more robust by using inject methods and introducing
a failsafe view which does simple php templating
in case critical errors (like doc comments disabled)
occur.

Resolves: #55352
Releases: 6.2
Change-Id: I424d6a290b65ae023ec19a745477cfaecdef72c7
Reviewed-on: https://review.typo3.org/27067
Tested-by: Alexander Opitz
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
typo3/sysext/install/Classes/Controller/Action/AbstractAction.php
typo3/sysext/install/Classes/Controller/Action/Common/InstallToolDisabledAction.php
typo3/sysext/install/Classes/Controller/Action/Step/EnvironmentAndFolders.php
typo3/sysext/install/Classes/Controller/StepController.php
typo3/sysext/install/Classes/Status/AlertStatus.php [new file with mode: 0644]
typo3/sysext/install/Classes/Status/StatusUtility.php
typo3/sysext/install/Classes/SystemEnvironment/Check.php
typo3/sysext/install/Classes/View/FailsafeView.php [new file with mode: 0644]
typo3/sysext/install/Resources/Private/Templates/Action/Common/InstallToolDisabled.phtml [new file with mode: 0644]
typo3/sysext/install/Resources/Private/Templates/Action/Step/EnvironmentAndFolders.phtml [new file with mode: 0644]

index d6fabfd..5233302 100644 (file)
@@ -33,17 +33,33 @@ abstract class AbstractAction implements ActionInterface {
 
        /**
         * @var \TYPO3\CMS\Extbase\Object\ObjectManager
-        * @inject
         */
        protected $objectManager = NULL;
 
        /**
-        * @var \TYPO3\CMS\Install\View\StandaloneView
-        * @inject
+        * Do NOT refactor to use @inject annotation, as failsafe handling would not work any more
+        *
+        * @param \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager
+        */
+       public function injectObjectManager(\TYPO3\CMS\Extbase\Object\ObjectManager $objectManager) {
+               $this->objectManager = $objectManager;
+       }
+
+       /**
+        * @var \TYPO3\CMS\Install\View\FailsafeView
         */
        protected $view = NULL;
 
        /**
+        * Do NOT refactor to use @inject annotation, as failsafe handling would not work any more
+        *
+        * @param \TYPO3\CMS\Install\View\FailsafeView $view
+        */
+       public function injectView(\TYPO3\CMS\Install\View\FailsafeView $view) {
+               $this->view = $view;
+       }
+
+       /**
         * @var string Name of controller. One of the strings 'step', 'tool' or 'common'
         */
        protected $controller = '';
index b9d5009..b72334e 100644 (file)
@@ -37,6 +37,13 @@ class InstallToolDisabledAction extends Action\AbstractAction {
         * @return string Rendered content
         */
        protected function executeAction() {
-               return $this->view->render();
+               /** @var \TYPO3\CMS\Install\SystemEnvironment\Check $statusCheck */
+               $statusCheck = $this->objectManager->get('TYPO3\\CMS\\Install\\SystemEnvironment\\Check');
+               $statusObjects = $statusCheck->getStatus();
+               /** @var \TYPO3\CMS\Install\Status\StatusUtility $statusUtility */
+               $statusUtility = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\StatusUtility');
+               $alerts = $statusUtility->filterBySeverity($statusObjects, 'alert');
+               $this->view->assign('alerts', $alerts);
+               return $this->view->render(!empty($alerts));
        }
 }
index 255978c..ae86aa8 100644 (file)
@@ -104,6 +104,8 @@ class EnvironmentAndFolders extends AbstractStepAction {
                /** @var \TYPO3\CMS\Install\Status\StatusUtility $statusUtility */
                $statusUtility = $this->objectManager->get('TYPO3\\CMS\\Install\\Status\\StatusUtility');
                $environmentStatus = $statusUtility->sortBySeverity($statusObjects);
+               $alerts = $statusUtility->filterBySeverity($statusObjects, 'alert');
+               $this->view->assign('alerts', $alerts);
                $this->view->assign('environmentStatus', $environmentStatus);
 
                /** @var $folderStructureFactory \TYPO3\CMS\Install\FolderStructure\DefaultFactory */
@@ -122,6 +124,6 @@ class EnvironmentAndFolders extends AbstractStepAction {
                        $this->view->assign('errorsOrWarningsFromStatus', TRUE);
                }
 
-               return $this->view->render();
+               return $this->view->render(!empty($alerts));
        }
 }
index 4924fb3..7142679 100644 (file)
@@ -380,8 +380,10 @@ class StepController extends AbstractController {
                        $this->redirect();
                }
 
+               $testReflection = new \ReflectionMethod(get_class($this), __FUNCTION__);
                if (!@is_dir(PATH_typo3conf)
                        || $needsExecution
+                       || $testReflection->getDocComment() === FALSE
                ) {
                        /** @var \TYPO3\CMS\Install\Controller\Action\Step\StepInterface $action */
                        $action = $this->objectManager->get('TYPO3\\CMS\\Install\\Controller\\Action\\Step\\EnvironmentAndFolders');
diff --git a/typo3/sysext/install/Classes/Status/AlertStatus.php b/typo3/sysext/install/Classes/Status/AlertStatus.php
new file mode 100644 (file)
index 0000000..99b6932
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+namespace TYPO3\CMS\Install\Status;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Christian Kuhn <lolli@schwarzbu.ch>
+ *  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!
+ ***************************************************************/
+
+/**
+ * Alert level status
+ */
+class AlertStatus extends AbstractStatus implements StatusInterface {
+
+       /**
+        * @var string The severity
+        */
+       protected $severity = 'alert';
+
+}
index 46376b7..85ee14f 100644 (file)
@@ -39,6 +39,7 @@ class StatusUtility {
         */
        public function sortBySeverity(array $statusObjects = array()) {
                $orderedStatus = array(
+                       'alert' => $this->filterBySeverity($statusObjects, 'alert'),
                        'error' => $this->filterBySeverity($statusObjects, 'error'),
                        'warning' => $this->filterBySeverity($statusObjects, 'warning'),
                        'ok' => $this->filterBySeverity($statusObjects, 'ok'),
index a5573bb..3a3c382 100644 (file)
@@ -807,16 +807,24 @@ class Check {
         */
        protected function checkReflectionDocComment() {
                $testReflection = new \ReflectionMethod(get_class($this), __FUNCTION__);
-               if (strlen($testReflection->getDocComment()) === 0) {
-                       $status = new Status\ErrorStatus();
+               if ($testReflection->getDocComment() === FALSE) {
+                       $status = new Status\AlertStatus();
                        $status->setTitle('PHP Doc comment reflection broken');
                        $status->setMessage(
-                               'TYPO3 CMS core extensions like extbase and fluid heavily rely on method' .
-                               ' comment parsing to fetch annotations and add magic according to them.' .
-                               ' This does not work in the current environment and will lead to a lot of' .
-                               ' broken extensions. The PHP extension eaccelerator is known to break this if' .
-                               ' it is compiled without --with-eaccelerator-doc-comment-inclusion flag.' .
-                               ' This compile flag must be given, otherwise TYPO3 CMS is no fun.'
+                               'TYPO3 CMS core extensions like extbase and fluid heavily rely on method'
+                               . ' comment parsing to fetch annotations and add magic belonging to them.'
+                               . ' This does not work in the current environment and so we can not install'
+                               . ' TYPO3 CMS.' . LF
+                               . ' Here are some possibilities: ' . LF
+                               . '* In Zend OPcache you can disable to save/load comment. If you are using'
+                               . ' Zend OPcache (included since PHP 5.5) then check your php.ini settings for'
+                               . ' opcache.save_comments and opcache.load_comments and enable them.' . LF
+                               . '* In Zend Optimizer+ you can disable to save comment. If you are using'
+                               . ' Zend Optimizer+ then check your php.ini settings for'
+                               . ' zend_optimizerplus.save_comments and enable it.' . LF
+                               . '* The PHP extension eaccelerator is known to break this if'
+                               . ' it is compiled without --with-eaccelerator-doc-comment-inclusion flag.'
+                               . ' This compile flag must be given, otherwise TYPO3 CMS will not work.'
                        );
                } else {
                        $status = new Status\OkStatus();
diff --git a/typo3/sysext/install/Classes/View/FailsafeView.php b/typo3/sysext/install/Classes/View/FailsafeView.php
new file mode 100644 (file)
index 0000000..22a98ac
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+namespace TYPO3\CMS\Install\View;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Helmut Hummel <helmut.hummel@typo3.org>
+ *  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\Core\Utility\GeneralUtility;
+
+/**
+ * A view with basically wraps the standalone view for normal conditions
+ * and implements a renderAlertStatus message for alert conditions
+ * which would also make the install tool to fail.
+ */
+class FailsafeView extends \TYPO3\CMS\Extbase\Mvc\View\AbstractView {
+
+       /**
+        * @var string
+        */
+       protected $templatePathAndFileName;
+
+       /**
+        * @var string
+        */
+       protected $layoutRootPath;
+
+       /**
+        * @var string
+        */
+       protected $partialRootPath;
+
+       /**
+        * @var \TYPO3\CMS\Extbase\Object\ObjectManager
+        */
+       protected $objectManager = NULL;
+
+       /**
+        * Constructor
+        */
+       public function __construct() {
+               $this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
+       }
+
+       /**
+        * Hand over regular rendering to standalone view,
+        * or render alert status
+        *
+        * @param bool $alert
+        * @return string
+        */
+       public function render($alert = FALSE) {
+               if ($alert) {
+                       return $this->renderAlertStatus();
+               }
+               /** @var \TYPO3\CMS\Install\View\StandaloneView $realView */
+               $realView = $this->objectManager->get('TYPO3\\CMS\\Install\\View\\StandaloneView');
+               $realView->assignMultiple($this->variables);
+               $realView->setTemplatePathAndFilename($this->templatePathAndFileName);
+               $realView->setLayoutRootPath($this->layoutRootPath);
+               $realView->setPartialRootPath($this->partialRootPath);
+
+               return $realView->render();
+       }
+
+       /**
+        * In case an alert happens we fall back to a simple PHP template
+        *
+        * @return string
+        */
+       protected function renderAlertStatus() {
+               $templatePath = preg_replace('#\.html$#', '.phtml', $this->templatePathAndFileName);
+               ob_start();
+               include $templatePath;
+               $renderedTemplate = ob_get_contents();
+               ob_end_clean();
+
+               return $renderedTemplate;
+       }
+
+       /**
+        * @param string $templatePathAndFileName
+        */
+       public function setTemplatePathAndFileName($templatePathAndFileName) {
+               $this->templatePathAndFileName = $templatePathAndFileName;
+       }
+
+       /**
+        * @param string $layoutRootPath
+        */
+       public function setLayoutRootPath($layoutRootPath) {
+               $this->layoutRootPath = $layoutRootPath;
+       }
+
+       /**
+        * @param string $partialRootPath
+        */
+       public function setPartialRootPath($partialRootPath) {
+               $this->partialRootPath = $partialRootPath;
+       }
+}
diff --git a/typo3/sysext/install/Resources/Private/Templates/Action/Common/InstallToolDisabled.phtml b/typo3/sysext/install/Resources/Private/Templates/Action/Common/InstallToolDisabled.phtml
new file mode 100644 (file)
index 0000000..c322b74
--- /dev/null
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+       <title>The Install Tool is locked</title>
+       <link rel="stylesheet" type="text/css" href="../Resources/Public/Stylesheets/Action/Common/EarlyExit.css?<?= $this->variables['time'] ?>" />
+</head>
+<body>
+<div id="container">
+       <h1>TYPO3</h1>
+       <div class="typo3-message message-warning">
+               <h2>The Install Tool is locked</h2>
+               <p>
+                       To enable the Install Tool, the file ENABLE_INSTALL_TOOL must be created.
+               </p>
+               <ul>
+                       <li>
+                               In the typo3conf/ folder, create a file named ENABLE_INSTALL_TOOL. The file name is
+                               case sensitive, but the file itself can simply be an empty file.
+                       </li>
+                       <li>
+                               You are recommended to log out from the Install Tool after finishing your work.
+                               The file will then automatically be deleted.
+                       </li>
+               </ul>
+               <p>
+                       For security reasons, it is highly recommended that you either rename or delete the file after the operation is finished.
+               </p>
+               <p>
+                       As an additional security measure, if the file is older than one hour, TYPO3 will automatically delete it. The file must be writable by the web server user.
+               </p>
+       </div>
+</div>
+</body>
+</html>
diff --git a/typo3/sysext/install/Resources/Private/Templates/Action/Step/EnvironmentAndFolders.phtml b/typo3/sysext/install/Resources/Private/Templates/Action/Step/EnvironmentAndFolders.phtml
new file mode 100644 (file)
index 0000000..e0eaf9a
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+       <title>The Install Tool is locked</title>
+       <link rel="stylesheet" type="text/css" href="../Resources/Public/Stylesheets/Action/Common/EarlyExit.css?<?= $this->variables['time'] ?>" />
+       <link rel="stylesheet" type="text/css" href="../Resources/Public/Stylesheets/Action/Step/General.css?<?= $this->variables['time'] ?>" />
+</head>
+<body>
+<div id="container">
+       <h1>TYPO3</h1>
+       <?php if (!empty($this->variables['alerts'])): ?>
+               <?php foreach ($this->variables['alerts'] as $message): ?>
+                               <div class="typo3-message message-error">
+                                       <div class="header-container">
+                                               <div class="message-header message-left"><strong><?= htmlspecialchars($message->getTitle()) ?></strong></div>
+                                               <div class="message-header message-right"></div>
+                                       </div>
+                                       <div class="message-body">
+                                               <?php echo nl2br(htmlspecialchars($message->getMessage()))?>
+                                       </div>
+                               </div>
+                               <p></p>
+               <?php endforeach; ?>
+       <?php endif; ?>
+       <?php if (!empty($this->variables['environmentStatus']['error'])): ?>
+               <?php foreach ($this->variables['environmentStatus']['error'] as $message): ?>
+                               <div class="typo3-message message-<?= htmlspecialchars($message->getSeverity()) ?>">
+                                       <div class="header-container">
+                                               <div class="message-header message-left"><strong><?= htmlspecialchars($message->getTitle()) ?></strong></div>
+                                               <div class="message-header message-right"></div>
+                                       </div>
+                                       <div class="message-body">
+                                               <?php echo nl2br(htmlspecialchars($message->getMessage()))?>
+                                       </div>
+                               </div>
+                               <p></p>
+               <?php endforeach; ?>
+       <?php endif; ?>
+       <?php if (!empty($this->variables['environmentStatus']['warning'])): ?>
+               <?php foreach ($this->variables['environmentStatus']['warning'] as $message): ?>
+                               <div class="typo3-message message-<?= htmlspecialchars($message->getSeverity()) ?>">
+                                       <div class="header-container">
+                                               <div class="message-header message-left"><strong><?= htmlspecialchars($message->getTitle()) ?></strong></div>
+                                               <div class="message-header message-right"></div>
+                                       </div>
+                                       <div class="message-body">
+                                               <?php echo nl2br(htmlspecialchars($message->getMessage()))?>
+                                       </div>
+                               </div>
+                               <p></p>
+               <?php endforeach; ?>
+       <?php endif; ?>
+</div>
+</body>
+</html>
\ No newline at end of file