diff --git a/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php b/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php index 64c6df3ade56dd0c3eb7326887958dd0bcc5f813..38c5d073db07bca46e52094d1bb5514aa8db01d1 100644 --- a/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php +++ b/typo3/sysext/backend/Classes/Http/BackendModuleRequestHandler.php @@ -164,14 +164,6 @@ class BackendModuleRequestHandler implements RequestHandlerInterface if (isset($moduleConfiguration['routeTarget'])) { $dispatcher = GeneralUtility::makeInstance(Dispatcher::class); $this->request = $this->request->withAttribute('target', $moduleConfiguration['routeTarget']); - // @internal routeParameters are a helper construct for the install tool only. - // @todo: remove this, after sub-actions in install tool can be addressed directly - if (!empty($moduleConfiguration['routeParameters'])) { - $this->request = $this->request->withQueryParams(array_merge_recursive( - $this->request->getQueryParams(), - $moduleConfiguration['routeParameters'] - )); - } $response = $dispatcher->dispatch($this->request, $response); } else { // extbase module diff --git a/typo3/sysext/core/Tests/Acceptance/Backend/Install/InstallModuleCest.php b/typo3/sysext/core/Tests/Acceptance/Backend/Install/InstallModuleCest.php deleted file mode 100644 index b6fbff433cac859e383e9a369ef2b68a32380bf9..0000000000000000000000000000000000000000 --- a/typo3/sysext/core/Tests/Acceptance/Backend/Install/InstallModuleCest.php +++ /dev/null @@ -1,112 +0,0 @@ -<?php -namespace TYPO3\CMS\Core\Tests\Acceptance\Backend\Language; - -/* - * This file is part of the TYPO3 CMS project. - * - * It is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License, either version 2 - * of the License, or any later version. - * - * For the full copyright and license information, please read the - * LICENSE.txt file that was distributed with this source code. - * - * The TYPO3 project - inspiring people to share! - */ - -use TYPO3\TestingFramework\Core\Acceptance\Step\Backend\Admin; - -/** - * Install Module tests - */ -class InstallModuleCest -{ - /** - * @var string - */ - protected $password = ''; - - /** - * @param Admin $I - */ - public function _before(Admin $I) - { - $this->password = getenv('typo3InstallToolPassword'); - - $I->useExistingSession(); - // Ensure main content frame is fully loaded, otherwise there are load-race-conditions - $I->switchToIFrame('list_frame'); - $I->waitForText('Web Content Management System'); - $I->switchToIFrame(); - - $I->see('Maintenance'); - $I->click('Maintenance'); - - // switch to content iframe - $I->switchToIFrame('list_frame'); - } - - /** - * @param Admin $I - */ - public function unlockAndLockInstallTool(Admin $I) - { - $I->wantTo('Check the Install Tool unlock and lock functions.'); - - // @todo probably there is a better solution skipping the test - if (empty($this->password)) { - $I->comment('Skip this test.'); - } else { - $I->amGoingTo('unlock the install tool'); - $I->waitForElement('#t3-install-form-unlock'); - $I->see('The Install Tool is locked'); - $I->see('Unlock the Install Tool'); - $I->click('//button[@value="enableInstallTool"]'); - $I->waitForElement('#t3-install-outer'); - $I->see('Password'); - $I->see('Login'); - - $I->amGoingTo('lock the install tool'); - $I->see('Lock Install Tool again'); - $I->click('Lock Install Tool again'); - $I->see('The Install Tool is locked'); - } - } - - /** - * @param Admin $I - */ - public function loginToInstallTool(Admin $I) - { - $I->wantTo('Check the Install Tool Login with wrong and right passwords.'); - - // @todo probably there is a better solution skipping the test - if (empty($this->password)) { - $I->comment('Skip this test.'); - } else { - $I->amGoingTo('unlock the install tool'); - $I->waitForElement('#t3-install-form-unlock'); - $I->see('The Install Tool is locked'); - $I->see('Unlock the Install Tool'); - $I->click('//button[@value="enableInstallTool"]'); - $I->waitForElement('#t3-install-outer'); - - $I->amGoingTo('login to install tool with wrong password'); - $I->fillField('#t3-install-form-password', 'wrong_' . $this->password); - $I->click('//button[@type="submit"]'); - $I->waitForElement('//div[@class="t3js-message typo3-message alert alert-danger"]'); - $I->see('Login failed'); - $I->see('Given password does not match the install tool login password.'); - $I->see('Calculated hash:'); - - $I->amGoingTo('login to install tool with right password'); - $I->fillField('#t3-install-form-password', $this->password); - $I->click('//button[@type="submit"]'); - $I->waitForElement('//body[@class="backend"]'); - $I->see('Lock Install Tool'); - - $I->click('Lock Install Tool'); - $I->see('The Install Tool is locked'); - } - } -} diff --git a/typo3/sysext/install/Classes/Controller/AbstractController.php b/typo3/sysext/install/Classes/Controller/AbstractController.php index b4a0303947b6f32ec953f2a08f2b47a3cadeedcf..d7e95f57639f8bc72d07bfd6b2ea223360439a34 100644 --- a/typo3/sysext/install/Classes/Controller/AbstractController.php +++ b/typo3/sysext/install/Classes/Controller/AbstractController.php @@ -44,6 +44,7 @@ class AbstractController $action = GeneralUtility::makeInstance(LoginForm::class); $action->setController('common'); $action->setAction('login'); + $action->setContext($request->getAttribute('context', 'standalone')); $action->setToken($this->generateTokenForAction('login')); $action->setPostValues($request->getParsedBody()['install'] ?? []); if ($message) { @@ -146,13 +147,6 @@ class AbstractController } $parameters[] = 'install[redirectCount]=' . $redirectCount; - // Add context parameter in case this script was called within backend scope - $context = 'install[context]=standalone'; - if (isset($getPostValues['context']) && $getPostValues['context'] === 'backend') { - $context = 'install[context]=backend'; - } - $parameters[] = $context; - // Add controller parameter $controllerParameter = 'install[controller]=step'; if ((isset($getPostValues['controller']) && $getPostValues['controller'] === 'tool') diff --git a/typo3/sysext/install/Classes/Controller/Action/AbstractAction.php b/typo3/sysext/install/Classes/Controller/Action/AbstractAction.php index 0bbfde1ddc8cae56977ff39797f9ddf7071596b7..a1fcaa1191a234e4d274403b166ea468c42e4744 100644 --- a/typo3/sysext/install/Classes/Controller/Action/AbstractAction.php +++ b/typo3/sysext/install/Classes/Controller/Action/AbstractAction.php @@ -16,6 +16,7 @@ namespace TYPO3\CMS\Install\Controller\Action; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; +use TYPO3\CMS\Install\Service\ContextService; /** * General purpose controller action helper methods and bootstrap @@ -52,6 +53,11 @@ abstract class AbstractAction implements ActionInterface */ protected $messages = []; + /** + * @var ContextService + */ + protected $contextService; + /** * Handles the action * @@ -68,9 +74,6 @@ abstract class AbstractAction implements ActionInterface */ protected function initializeHandle() { - // Context service distinguishes between standalone and backend context - $contextService = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Service\ContextService::class); - $viewRootPath = GeneralUtility::getFileAbsFileName('EXT:install/Resources/Private/'); $controllerActionDirectoryName = ucfirst($this->controller); $mainTemplate = ucfirst($this->action); @@ -85,8 +88,8 @@ abstract class AbstractAction implements ActionInterface ->assign('action', $this->action) ->assign('controller', $this->controller) ->assign('token', $this->token) - ->assign('context', $contextService->getContextString()) - ->assign('contextService', $contextService) + ->assign('context', $this->contextService->getContextString()) + ->assign('contextService', $this->contextService) ->assign('messages', $this->messages) ->assign('typo3Version', TYPO3_version) ->assign('siteName', $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename']); @@ -152,17 +155,13 @@ abstract class AbstractAction implements ActionInterface /** * Context determines if the install tool is called within backend or standalone + * This method creates a context service that distinguishes between standalone and backend context * - * @return string Either 'standalone' or 'backend' + * @param $context string Either 'standalone' or 'backend' */ - protected function getContext() + public function setContext($context) { - $context = 'standalone'; - $formValues = GeneralUtility::_GP('install'); - if (isset($formValues['context'])) { - $context = $formValues['context'] === 'backend' ? 'backend' : 'standalone'; - } - return $context; + $this->contextService = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Service\ContextService::class, $context); } /** diff --git a/typo3/sysext/install/Classes/Controller/Action/ActionInterface.php b/typo3/sysext/install/Classes/Controller/Action/ActionInterface.php index 01f5e2f72459c204beb95d91b05c631a09e4e5c2..c39096ac527cb2cb878ab3d86e97cdc1636f6ab4 100644 --- a/typo3/sysext/install/Classes/Controller/Action/ActionInterface.php +++ b/typo3/sysext/install/Classes/Controller/Action/ActionInterface.php @@ -48,6 +48,13 @@ interface ActionInterface */ public function setAction($action); + /** + * Set the context name, can be "installer", "standalone" or "backend" + * + * @param string $context + */ + public function setContext($context); + /** * Set POST values * diff --git a/typo3/sysext/install/Classes/Controller/AjaxController.php b/typo3/sysext/install/Classes/Controller/AjaxController.php index 5bca62a4f4c40325ba040f2cd478b06d17046310..b1d2316dff683f55db7452074799464ef294bf0d 100644 --- a/typo3/sysext/install/Classes/Controller/AjaxController.php +++ b/typo3/sysext/install/Classes/Controller/AjaxController.php @@ -111,6 +111,7 @@ class AjaxController extends AbstractController } $toolAction->setController('ajax'); $toolAction->setAction($action); + $toolAction->setContext($request->getAttribute('context', 'standalone')); $toolAction->setToken($this->generateTokenForAction($action)); $toolAction->setPostValues($request->getParsedBody()['install'] ?? []); return $this->output($toolAction->handle()); diff --git a/typo3/sysext/install/Classes/Controller/BackendModuleController.php b/typo3/sysext/install/Classes/Controller/BackendModuleController.php index c5f0aba7be990eb1c16b41fc1d923a5ea765d789..e7351f526c231df4f9600167ac3916ba04a6d2e7 100644 --- a/typo3/sysext/install/Classes/Controller/BackendModuleController.php +++ b/typo3/sysext/install/Classes/Controller/BackendModuleController.php @@ -16,17 +16,9 @@ namespace TYPO3\CMS\Install\Controller; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use TYPO3\CMS\Backend\Template\ModuleTemplate; -use TYPO3\CMS\Core\FormProtection\FormProtectionFactory; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Fluid\View\StandaloneView; -use TYPO3\CMS\Install\Service\EnableFileService; /** - * Backend module controller - * - * Embeds in backend and only shows the 'enable install tool button' or redirects - * to step installer if install tool is enabled. + * Backend module controller to dispatch to the main modules or to an AJAX request * * This is a classic backend module that does not interfere with other code * within the install tool, it can be seen as a facade around install tool just @@ -35,62 +27,82 @@ use TYPO3\CMS\Install\Service\EnableFileService; class BackendModuleController { /** - * Index action shows install tool / step installer or redirect to action to enable install tool + * Renders the maintenance tool action (or AJAX, if it was specifically requested) * * @param ServerRequestInterface $request * @param ResponseInterface $response * @return ResponseInterface - * @throws \RuntimeException */ - public function index(ServerRequestInterface $request, ResponseInterface $response) + public function maintenanceAction(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface { - $enableFileService = GeneralUtility::makeInstance(EnableFileService::class); - - $formProtection = FormProtectionFactory::get(); - - $targetUrl = 'install.php?install[context]=backend'; - if (!empty($request->getQueryParams()['install']['action'])) { - $subAction = !empty($request->getQueryParams()['install']['action']) - ? $request->getQueryParams()['install']['action'] - : ''; - $targetUrl .= '&install[controller]=tool&install[action]=' . $subAction; - } - - if ($enableFileService->checkInstallToolEnableFile()) { - // Install tool is open and valid, redirect to it - $response = $response - ->withStatus(303) - ->withHeader('Location', $targetUrl); - } elseif ($request->getMethod() === 'POST' && $request->getParsedBody()['action'] === 'enableInstallTool') { - // Request to open the install tool - $installToolEnableToken = $request->getParsedBody()['installToolEnableToken']; - if (!$formProtection->validateToken($installToolEnableToken, 'installTool')) { - throw new \RuntimeException('Given form token was not valid', 1369161225); - } - $enableFileService->createInstallToolEnableFile(); + return $this->executeSpecificToolAction($request, 'maintenance'); + } - // Install tool is open and valid, redirect to it - $response = $response - ->withStatus(303) - ->withHeader('Location', $targetUrl); - } else { - // Show the "create enable install tool" button - $token = $formProtection->generateToken('installTool'); + /** + * Renders the settings tool action (or AJAX, if it was specifically requested) + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + */ + public function settingsAction(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface + { + return $this->executeSpecificToolAction($request, 'settings'); + } - $view = GeneralUtility::makeInstance(StandaloneView::class); - $view->setTemplatePathAndFilename( - GeneralUtility::getFileAbsFileName( - 'EXT:install/Resources/Private/Templates/BackendModule/ShowEnableInstallToolButton.html' - ) - ); - $view->assign('installToolEnableToken', $token); + /** + * Renders the upgrade tool action (or AJAX, if it was specifically requested) + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + */ + public function upgradeAction(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface + { + return $this->executeSpecificToolAction($request, 'upgrade'); + } - $moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class); - $moduleTemplate->setContent($view->render()); + /** + * Renders the environment tool action (or AJAX, if it was specifically requested) + * + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @return ResponseInterface + */ + public function environmentAction(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface + { + return $this->executeSpecificToolAction($request, 'environment'); + } - $response->getBody()->write($moduleTemplate->renderContent()); + /** + * Sets the action inside the install tool to a specific action and calls the "toolcontroller" afterwards + * + * @param ServerRequestInterface $request + * @param $action + * @return ResponseInterface + */ + protected function executeSpecificToolAction(ServerRequestInterface $request, $action): ResponseInterface + { + $request = $request->withAttribute('context', 'backend'); + // Can be moved into one controller in my opinion now, or should go into a dispatcher that + // also deals with actions + if ($request->getQueryParams()['install']['controller'] === 'ajax') { + return $this->handleAjaxRequest($request); } + $queryParameters = $request->getQueryParams(); + $queryParameters['install']['action'] = $action; + $request = $request->withQueryParams($queryParameters); + return (new ToolController())->execute($request); + } - return $response; + /** + * Calls the AJAX controller (if requested as "controller") + * + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + protected function handleAjaxRequest(ServerRequestInterface $request): ResponseInterface + { + return (new AjaxController())->execute($request); } } diff --git a/typo3/sysext/install/Classes/Controller/StepController.php b/typo3/sysext/install/Classes/Controller/StepController.php index ac8806373399332f9f9fcd5c160302428e5fd641..311c0c7e456c626ba86971ce3d9ebd26247cbc86 100644 --- a/typo3/sysext/install/Classes/Controller/StepController.php +++ b/typo3/sysext/install/Classes/Controller/StepController.php @@ -82,6 +82,7 @@ class StepController extends AbstractController $action = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Controller\Action\Common\InstallToolDisabledAction::class); $action->setAction('installToolDisabled'); } + $action->setContext('standalone'); $action->setController('common'); return $this->output($action->handle()); } @@ -97,6 +98,7 @@ class StepController extends AbstractController /** @var \TYPO3\CMS\Install\Controller\Action\ActionInterface $action */ $action = GeneralUtility::makeInstance(\TYPO3\CMS\Install\Controller\Action\Common\InstallToolPasswordNotSetAction::class); $action->setController('common'); + $action->setContext('standalone'); $action->setAction('installToolPasswordNotSet'); return $this->output($action->handle()); } @@ -117,6 +119,7 @@ class StepController extends AbstractController /** @var AbstractStepAction $stepAction */ $stepAction = $this->getActionInstance($action); $stepAction->setAction($action); + $stepAction->setContext('standalone'); $stepAction->setToken($this->generateTokenForAction($action)); $stepAction->setPostValues($postValues); $messages = $stepAction->execute(); @@ -146,6 +149,7 @@ class StepController extends AbstractController $stepAction = $this->getActionInstance($action); $stepAction->setAction($action); $stepAction->setController('step'); + $stepAction->setContext('standalone'); $stepAction->setToken($this->generateTokenForAction($action)); $stepAction->setPostValues($postValues); @@ -238,6 +242,7 @@ class StepController extends AbstractController $action->setStepsCounter($currentStep, $totalSteps); } $action->setController('step'); + $action->setContext('standalone'); $action->setAction('environmentAndFolders'); if (!empty($errorMessagesFromExecute)) { $action->setMessages($errorMessagesFromExecute); diff --git a/typo3/sysext/install/Classes/Controller/ToolController.php b/typo3/sysext/install/Classes/Controller/ToolController.php index 7b8117bd320e98c781a60983ed7fee8a87f34b42..205329ddd7c93efe36a8343d71b3bc8587a7e941 100644 --- a/typo3/sysext/install/Classes/Controller/ToolController.php +++ b/typo3/sysext/install/Classes/Controller/ToolController.php @@ -62,6 +62,7 @@ class ToolController extends AbstractController $toolAction->setController('tool'); $toolAction->setAction($action); $toolAction->setToken($this->generateTokenForAction($action)); + $toolAction->setContext($request->getAttribute('context', 'standalone')); $toolAction->setPostValues($request->getParsedBody()['install'] ?? []); return $this->output($toolAction->handle()); } diff --git a/typo3/sysext/install/Classes/Service/ContextService.php b/typo3/sysext/install/Classes/Service/ContextService.php index e1f256d7954cd4521e8dc913398d5edb420ce3fd..ca8d3311ca56c7a59a4d74ee0e311983d107fa6d 100644 --- a/typo3/sysext/install/Classes/Service/ContextService.php +++ b/typo3/sysext/install/Classes/Service/ContextService.php @@ -26,13 +26,12 @@ class ContextService /** * Constructor, prepare the context information + * + * @param string $context */ - public function __construct() + public function __construct($context) { - $formValues = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('install'); - if (isset($formValues['context'])) { - $this->backendContext = ($formValues['context'] === 'backend'); - } + $this->backendContext = ($context === 'backend'); } /** diff --git a/typo3/sysext/install/ext_tables.php b/typo3/sysext/install/ext_tables.php index 7b8b734ca79899af255bb6118497e9a4fa9bd758..2b0b31d3baf08700ca0429748970e3664ad58360 100644 --- a/typo3/sysext/install/ext_tables.php +++ b/typo3/sysext/install/ext_tables.php @@ -17,12 +17,7 @@ if (TYPO3_MODE === 'BE') { '', '', [ - 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::index', - 'routeParameters' => [ - 'install' => [ - 'action' => 'maintenance' - ] - ], + 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::maintenanceAction', 'access' => 'systemMaintainer', 'name' => 'tools_toolsmaintenance', 'iconIdentifier' => 'module-install-maintenance', @@ -35,12 +30,7 @@ if (TYPO3_MODE === 'BE') { '', '', [ - 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::index', - 'routeParameters' => [ - 'install' => [ - 'action' => 'settings' - ] - ], + 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::settingsAction', 'access' => 'systemMaintainer', 'name' => 'tools_toolssettings', 'iconIdentifier' => 'module-install-settings', @@ -53,12 +43,7 @@ if (TYPO3_MODE === 'BE') { '', '', [ - 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::index', - 'routeParameters' => [ - 'install' => [ - 'action' => 'upgrade' - ] - ], + 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::upgradeAction', 'access' => 'systemMaintainer', 'name' => 'tools_toolsupgrade', 'iconIdentifier' => 'module-install-upgrade', @@ -71,12 +56,7 @@ if (TYPO3_MODE === 'BE') { '', '', [ - 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::index', - 'routeParameters' => [ - 'install' => [ - 'action' => 'environment' - ] - ], + 'routeTarget' => \TYPO3\CMS\Install\Controller\BackendModuleController::class . '::environmentAction', 'access' => 'systemMaintainer', 'name' => 'tools_toolsenvironment', 'iconIdentifier' => 'module-install-environment',