From 1eeedc59379b1698006c3b8607705df3367e0d91 Mon Sep 17 00:00:00 2001 From: Susanne Moog <susanne.moog@typo3.org> Date: Thu, 5 Apr 2018 13:09:41 +0200 Subject: [PATCH] [TASK] Decouple adminPanel from frontend The admin panel has been extracted into an own extension. To enable users to de-activate the admin panel completely, the hard coupling between the extension and other parts of the core had to be resolved. With this change, the initialization of both adminPanel and feedit were moved into PSR-15 middlewares. Additionally all parameters related to the adminPanel were removed from the FrontendBackend- UserAuthentication. As feedit is tigthly coupled with the adminPanel some changes had to be made to its initialization, too. The flow of the adminPanel initialization and rendering were streamlined to allow modules to make use of the request object. Due to these changes in the control flow of the application the two existing tests were removed and new tests will be rewritten once the API is declared as stable. Releases: master Resolves: #84641 Change-Id: I72beefde0d792d3f4295c45aa27204c817d2de7a Reviewed-on: https://review.typo3.org/56558 Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Andreas Fernandez <a.fernandez@scripting-base.de> Tested-by: Andreas Fernandez <a.fernandez@scripting-base.de> Reviewed-by: Benni Mack <benni@typo3.org> Tested-by: Benni Mack <benni@typo3.org> --- .../Classes/Controller/MainController.php | 176 +++++++++++ .../adminpanel/Classes/Hooks/RenderHook.php | 56 ++++ .../Middleware/AdminPanelInitiator.php | 69 +++++ .../Classes/Modules/AbstractModule.php | 29 +- .../Modules/AdminPanelModuleInterface.php | 9 +- .../Classes/Modules/CacheModule.php | 3 +- .../adminpanel/Classes/Modules/EditModule.php | 11 +- .../Classes/Modules/PreviewModule.php | 8 +- .../Classes/Modules/TsDebugModule.php | 5 +- .../Repositories/FrontendGroupsRepository.php | 4 +- .../Classes/Service/EditToolbarService.php | 273 +++++++++++++++++ .../Classes/View/AdminPanelView.php | 287 ++---------------- .../Configuration/RequestMiddlewares.php | 22 ++ .../Tests/Unit/View/AdminPanelViewTest.php | 78 ----- .../AdminPanelDisabledModuleFixture.php | 141 --------- ...edShownOnSubmitInitializeModuleFixture.php | 142 --------- typo3/sysext/adminpanel/composer.json | 7 +- typo3/sysext/adminpanel/ext_localconf.php | 3 + .../FrontendBackendUserAuthentication.php | 57 ++-- ...641-DeprecatedAdminPanelRelatedMethods.rst | 53 ++++ .../feedit/Classes/FrontendEditPanel.php | 7 +- .../Middleware/FrontendEditInitiator.php | 67 ++++ .../Configuration/RequestMiddlewares.php | 21 ++ typo3/sysext/feedit/composer.json | 8 +- .../frontend/Classes/Http/RequestHandler.php | 7 +- .../Middleware/BackendUserAuthenticator.php | 3 +- typo3/sysext/frontend/composer.json | 3 + .../Php/MethodCallMatcher.php | 35 +++ .../Php/PropertyPublicMatcher.php | 15 + .../Private/Language/locallang_tsfe.xlf | 3 + .../PreviewUserAuthentication.php | 31 +- 31 files changed, 923 insertions(+), 710 deletions(-) create mode 100644 typo3/sysext/adminpanel/Classes/Controller/MainController.php create mode 100644 typo3/sysext/adminpanel/Classes/Hooks/RenderHook.php create mode 100644 typo3/sysext/adminpanel/Classes/Middleware/AdminPanelInitiator.php create mode 100644 typo3/sysext/adminpanel/Classes/Service/EditToolbarService.php create mode 100644 typo3/sysext/adminpanel/Configuration/RequestMiddlewares.php delete mode 100644 typo3/sysext/adminpanel/Tests/Unit/View/AdminPanelViewTest.php delete mode 100644 typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelDisabledModuleFixture.php delete mode 100644 typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelEnabledShownOnSubmitInitializeModuleFixture.php create mode 100644 typo3/sysext/core/Documentation/Changelog/master/Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst create mode 100644 typo3/sysext/feedit/Classes/Middleware/FrontendEditInitiator.php create mode 100644 typo3/sysext/feedit/Configuration/RequestMiddlewares.php diff --git a/typo3/sysext/adminpanel/Classes/Controller/MainController.php b/typo3/sysext/adminpanel/Classes/Controller/MainController.php new file mode 100644 index 000000000000..1ffdb97950d6 --- /dev/null +++ b/typo3/sysext/adminpanel/Classes/Controller/MainController.php @@ -0,0 +1,176 @@ +<?php +declare(strict_types = 1); + +namespace TYPO3\CMS\Adminpanel\Controller; + +/* + * 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\CMS\Adminpanel\Modules\AdminPanelModuleInterface; +use TYPO3\CMS\Adminpanel\View\AdminPanelView; +use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; +use TYPO3\CMS\Core\Cache\CacheManager; +use TYPO3\CMS\Core\Http\ServerRequest; +use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Service\DependencyOrderingService; +use TYPO3\CMS\Core\SingletonInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +/** + * Main controller for the admin panel + * + * @internal + */ +class MainController implements SingletonInterface +{ + /** + * @var array<AdminPanelModuleInterface> + */ + protected $modules = []; + + /** + * Initializes settings for the admin panel. + * + * @param \TYPO3\CMS\Core\Http\ServerRequest $request + */ + public function initialize(ServerRequest $request): void + { + $this->validateSortAndInitializeModules(); + $this->saveConfiguration(); + + foreach ($this->modules as $module) { + if ($module->isEnabled()) { + $module->initializeModule($request); + } + } + } + + /** + * Renders the panel - Is currently called via RenderHook in postProcessOutput + * + * @todo Still uses the legacy AdminpanelView and should be rewritten to fluid + * + * @return string + */ + public function render(): string + { + // handling via legacy functions + $adminPanelView = GeneralUtility::makeInstance(AdminPanelView::class); + $adminPanelView->setModules($this->modules); + return $adminPanelView->display(); + } + + /** + * Save admin panel configuration to backend user UC + */ + protected function saveConfiguration(): void + { + $input = GeneralUtility::_GP('TSFE_ADMIN_PANEL'); + $beUser = $this->getBackendUser(); + if (is_array($input)) { + // Setting + $beUser->uc['TSFE_adminConfig'] = array_merge( + !is_array($beUser->uc['TSFE_adminConfig']) ? [] : $beUser->uc['TSFE_adminConfig'], + $input + ); + unset($beUser->uc['TSFE_adminConfig']['action']); + + foreach ($this->modules as $module) { + if ($module->isEnabled() && $module->isOpen()) { + $module->onSubmit($input); + } + } + // Saving + $beUser->writeUC(); + // Flush fluid template cache + $cacheManager = new CacheManager(); + $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']); + $cacheManager->getCache('fluid_template')->flush(); + } + } + + /** + * Validates, sorts and initiates the registered modules + * + * @throws \RuntimeException + */ + protected function validateSortAndInitializeModules(): void + { + $modules = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? []; + if (empty($modules)) { + return; + } + foreach ($modules as $identifier => $configuration) { + if (empty($configuration) || !is_array($configuration)) { + throw new \RuntimeException( + 'Missing configuration for module "' . $identifier . '".', + 1519490105 + ); + } + if (!is_string($configuration['module']) || + empty($configuration['module']) || + !class_exists($configuration['module']) || + !is_subclass_of( + $configuration['module'], + AdminPanelModuleInterface::class + ) + ) { + throw new \RuntimeException( + 'The module "' . + $identifier . + '" defines an invalid module class. Ensure the class exists and implements the "' . + AdminPanelModuleInterface::class . + '".', + 1519490112 + ); + } + } + + $orderedModules = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies( + $modules + ); + + foreach ($orderedModules as $module) { + $this->modules[] = GeneralUtility::makeInstance($module['module']); + } + } + + /** + * Returns LanguageService + * + * @return LanguageService + */ + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } + + /** + * Returns the current BE user. + * + * @return FrontendBackendUserAuthentication + */ + protected function getBackendUser(): FrontendBackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + /** + * @return TypoScriptFrontendController + */ + protected function getTypoScriptFrontendController(): TypoScriptFrontendController + { + return $GLOBALS['TSFE']; + } +} diff --git a/typo3/sysext/adminpanel/Classes/Hooks/RenderHook.php b/typo3/sysext/adminpanel/Classes/Hooks/RenderHook.php new file mode 100644 index 000000000000..c0a5506a20f3 --- /dev/null +++ b/typo3/sysext/adminpanel/Classes/Hooks/RenderHook.php @@ -0,0 +1,56 @@ +<?php +declare(strict_types = 1); + +namespace TYPO3\CMS\Adminpanel\Hooks; + +/* + * 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\CMS\Adminpanel\Controller\MainController; +use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +/** + * Hook used to postProcess output - renders the admin panel + */ +class RenderHook +{ + + /** + * PostProcess output hook to render the admin panel + * We use a hook this late in the project to make sure all data is collected and can be displayed + * + * As the main content is already rendered, we use a string replace on the content to append the adminPanel + * to the HTML body. + * + * @param array $params + * @param TypoScriptFrontendController $pObj + */ + public function renderAdminPanel(array $params, TypoScriptFrontendController $pObj) + { + if ($pObj->isBackendUserLoggedIn() && + $GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication && + ( + !$GLOBALS['BE_USER']->extAdminConfig['hide'] && $pObj->config['config']['admPanel'] + ) + ) { + $mainController = GeneralUtility::makeInstance(MainController::class); + $pObj->content = str_ireplace( + '</body>', + $mainController->render() . '</body>', + $pObj->content + ); + } + } +} diff --git a/typo3/sysext/adminpanel/Classes/Middleware/AdminPanelInitiator.php b/typo3/sysext/adminpanel/Classes/Middleware/AdminPanelInitiator.php new file mode 100644 index 000000000000..b0dba87b80d1 --- /dev/null +++ b/typo3/sysext/adminpanel/Classes/Middleware/AdminPanelInitiator.php @@ -0,0 +1,69 @@ +<?php +declare(strict_types = 1); + +namespace TYPO3\CMS\Adminpanel\Middleware; + +/* + * 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 Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use TYPO3\CMS\Adminpanel\Controller\MainController; +use TYPO3\CMS\Adminpanel\View\AdminPanelView; +use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; +use TYPO3\CMS\Core\Utility\GeneralUtility; + +/** + * PSR-15 Middleware to initialize the admin panel + */ +class AdminPanelInitiator implements MiddlewareInterface +{ + + /** + * Initialize the adminPanel if + * - backend user is logged in + * - at least one adminpanel functionality is enabled + * + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * @return ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if ($GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication) { + + // Initialize admin panel since simulation settings are required here + $beUser = $GLOBALS['BE_USER']; + // set legacy config + $beUser->extAdminConfig = $beUser->getTSConfigProp('admPanel'); + $adminPanelConfiguration = $beUser->extAdminConfig; + if (isset($adminPanelConfiguration['enable.'])) { + foreach ($adminPanelConfiguration['enable.'] as $value) { + if ($value) { + $adminPanelController = GeneralUtility::makeInstance( + MainController::class + ); + $adminPanelController->initialize($request); + // legacy handling + $beUser->adminPanel = GeneralUtility::makeInstance(AdminPanelView::class); + $beUser->extAdmEnabled = true; + break; + } + } + } + } + return $handler->handle($request); + } +} diff --git a/typo3/sysext/adminpanel/Classes/Modules/AbstractModule.php b/typo3/sysext/adminpanel/Classes/Modules/AbstractModule.php index 07f3c61ec221..756ed7ccd4cf 100644 --- a/typo3/sysext/adminpanel/Classes/Modules/AbstractModule.php +++ b/typo3/sysext/adminpanel/Classes/Modules/AbstractModule.php @@ -1,5 +1,5 @@ <?php -declare(strict_types=1); +declare(strict_types = 1); namespace TYPO3\CMS\Adminpanel\Modules; @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Adminpanel\Modules; */ use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; +use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Localization\LanguageService; /** @@ -31,6 +32,16 @@ abstract class AbstractModule implements AdminPanelModuleInterface */ protected $extResources = 'EXT:adminpanel/Resources/Private'; + /** + * @var array + */ + protected $mainConfiguration; + + public function __construct() + { + $this->mainConfiguration = $this->getBackendUser()->getTSConfigProp('admPanel'); + } + /** * @inheritdoc */ @@ -42,7 +53,7 @@ abstract class AbstractModule implements AdminPanelModuleInterface /** * @inheritdoc */ - public function initializeModule(): void + public function initializeModule(ServerRequest $request): void { } @@ -59,8 +70,8 @@ abstract class AbstractModule implements AdminPanelModuleInterface { $identifier = $this->getIdentifier(); $result = $this->isEnabledViaTsConfig(); - if ($this->getBackendUser()->extAdminConfig['override.'][$identifier] ?? false) { - $result = (bool)$this->getBackendUser()->extAdminConfig['override.'][$identifier]; + if ($this->mainConfiguration['override.'][$identifier] ?? false) { + $result = (bool)$this->mainConfiguration['override.'][$identifier]; } return $result; } @@ -116,7 +127,7 @@ abstract class AbstractModule implements AdminPanelModuleInterface { $labelStr = $this->getLanguageService()->getLL($key); if ($convertWithHtmlspecialchars) { - $labelStr = htmlspecialchars($labelStr); + $labelStr = htmlspecialchars($labelStr, ENT_QUOTES | ENT_HTML5); } return $labelStr; } @@ -143,8 +154,8 @@ abstract class AbstractModule implements AdminPanelModuleInterface $beUser = $this->getBackendUser(); $identifier = $this->getIdentifier(); - if ($option && isset($beUser->extAdminConfig['override.'][$identifier . '.'][$option])) { - $returnValue = $beUser->extAdminConfig['override.'][$identifier . '.'][$option]; + if ($option && isset($this->mainConfiguration['override.'][$identifier . '.'][$option])) { + $returnValue = $this->mainConfiguration['override.'][$identifier . '.'][$option]; } else { $returnValue = $beUser->uc['TSFE_adminConfig'][$identifier . '_' . $option] ?? ''; } @@ -171,9 +182,9 @@ abstract class AbstractModule implements AdminPanelModuleInterface { $result = false; $identifier = $this->getIdentifier(); - if (!empty($this->getBackendUser()->extAdminConfig['enable.']['all'])) { + if (!empty($this->mainConfiguration['enable.']['all'])) { $result = true; - } elseif (!empty($this->getBackendUser()->extAdminConfig['enable.'][$identifier])) { + } elseif (!empty($this->mainConfiguration['enable.'][$identifier])) { $result = true; } return $result; diff --git a/typo3/sysext/adminpanel/Classes/Modules/AdminPanelModuleInterface.php b/typo3/sysext/adminpanel/Classes/Modules/AdminPanelModuleInterface.php index 12a4ab949d8c..f56445fdf9a5 100644 --- a/typo3/sysext/adminpanel/Classes/Modules/AdminPanelModuleInterface.php +++ b/typo3/sysext/adminpanel/Classes/Modules/AdminPanelModuleInterface.php @@ -1,5 +1,5 @@ <?php -declare(strict_types=1); +declare(strict_types = 1); namespace TYPO3\CMS\Adminpanel\Modules; @@ -16,6 +16,8 @@ namespace TYPO3\CMS\Adminpanel\Modules; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Http\ServerRequest; + /** * Interface for admin panel modules registered via EXTCONF * @@ -23,6 +25,7 @@ namespace TYPO3\CMS\Adminpanel\Modules; */ interface AdminPanelModuleInterface { + /** * Additional JavaScript code for this module * (you should only use vanilla JS here, as you cannot @@ -56,8 +59,10 @@ interface AdminPanelModuleInterface /** * Initialize the module - runs early in a TYPO3 request + * + * @param \TYPO3\CMS\Core\Http\ServerRequest $request */ - public function initializeModule(): void; + public function initializeModule(ServerRequest $request): void; /** * Module is enabled diff --git a/typo3/sysext/adminpanel/Classes/Modules/CacheModule.php b/typo3/sysext/adminpanel/Classes/Modules/CacheModule.php index 5a5fc636c4c0..78c86063545b 100644 --- a/typo3/sysext/adminpanel/Classes/Modules/CacheModule.php +++ b/typo3/sysext/adminpanel/Classes/Modules/CacheModule.php @@ -16,6 +16,7 @@ namespace TYPO3\CMS\Adminpanel\Modules; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -65,7 +66,7 @@ class CacheModule extends AbstractModule /** * @inheritdoc */ - public function initializeModule(): void + public function initializeModule(ServerRequest $request): void { if ($this->getConfigurationOption('noCache')) { $this->getTypoScriptFrontendController()->set_no_cache('Admin Panel: No Caching', true); diff --git a/typo3/sysext/adminpanel/Classes/Modules/EditModule.php b/typo3/sysext/adminpanel/Classes/Modules/EditModule.php index cb52bb43b387..a6cbbdf349d2 100644 --- a/typo3/sysext/adminpanel/Classes/Modules/EditModule.php +++ b/typo3/sysext/adminpanel/Classes/Modules/EditModule.php @@ -1,5 +1,5 @@ <?php -declare(strict_types=1); +declare(strict_types = 1); namespace TYPO3\CMS\Adminpanel\Modules; @@ -16,7 +16,9 @@ namespace TYPO3\CMS\Adminpanel\Modules; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Adminpanel\Service\EditToolbarService; use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -39,6 +41,7 @@ class EditModule extends AbstractModule $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath)); $view->setPartialRootPaths([$this->extResources . '/Partials']); + $editToolbarService = GeneralUtility::makeInstance(EditToolbarService::class); $view->assignMultiple([ 'feEdit' => ExtensionManagementUtility::isLoaded('feedit'), 'display' => [ @@ -46,7 +49,7 @@ class EditModule extends AbstractModule 'fieldIcons' => $this->getConfigurationOption('displayFieldIcons'), 'displayIcons' => $this->getConfigurationOption('displayIcons'), ], - 'toolbar' => $this->getBackendUser()->adminPanel->ext_makeToolBar(), + 'toolbar' => $editToolbarService->createToolbar(), 'script' => [ 'pageUid' => (int)$this->getTypoScriptFrontendController()->page['uid'], 'pageModule' => $this->getPageModule(), @@ -98,9 +101,11 @@ class EditModule extends AbstractModule * Initialize the edit module * Includes the frontend edit initialization * + * @param ServerRequest $request + * * @todo move into fe_edit (including the module) */ - public function initializeModule(): void + public function initializeModule(ServerRequest $request): void { $extFeEditLoaded = ExtensionManagementUtility::isLoaded('feedit'); $typoScriptFrontend = $this->getTypoScriptFrontendController(); diff --git a/typo3/sysext/adminpanel/Classes/Modules/PreviewModule.php b/typo3/sysext/adminpanel/Classes/Modules/PreviewModule.php index b22850aef03b..262b5c88c6fa 100644 --- a/typo3/sysext/adminpanel/Classes/Modules/PreviewModule.php +++ b/typo3/sysext/adminpanel/Classes/Modules/PreviewModule.php @@ -1,5 +1,5 @@ <?php -declare(strict_types=1); +declare(strict_types = 1); namespace TYPO3\CMS\Adminpanel\Modules; @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Adminpanel\Modules; */ use TYPO3\CMS\Adminpanel\Repositories\FrontendGroupsRepository; +use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -93,7 +94,10 @@ class PreviewModule extends AbstractModule return $this->getLanguageService()->sL($locallangFileAndPath); } - public function initializeModule(): void + /** + * @param ServerRequest $request + */ + public function initializeModule(ServerRequest $request): void { $this->initializeFrontendPreview(); if (GeneralUtility::_GP('ADMCMD_simUser')) { diff --git a/typo3/sysext/adminpanel/Classes/Modules/TsDebugModule.php b/typo3/sysext/adminpanel/Classes/Modules/TsDebugModule.php index 6b3323787e44..c888021053bc 100644 --- a/typo3/sysext/adminpanel/Classes/Modules/TsDebugModule.php +++ b/typo3/sysext/adminpanel/Classes/Modules/TsDebugModule.php @@ -1,5 +1,6 @@ <?php declare(strict_types = 1); + namespace TYPO3\CMS\Adminpanel\Modules; /* @@ -15,6 +16,7 @@ namespace TYPO3\CMS\Adminpanel\Modules; * The TYPO3 project - inspiring people to share! */ +use TYPO3\CMS\Core\Http\ServerRequest; use TYPO3\CMS\Core\TimeTracker\TimeTracker; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -74,7 +76,7 @@ class TsDebugModule extends AbstractModule /** * @inheritdoc */ - public function initializeModule(): void + public function initializeModule(ServerRequest $request): void { $typoScriptFrontend = $this->getTypoScriptFrontendController(); $typoScriptFrontend->forceTemplateParsing = (bool)$this->getConfigurationOption('forceTemplateParsing'); @@ -111,7 +113,6 @@ class TsDebugModule extends AbstractModule /** * Renders the TypoScript log as string * - * @param $output * @return string */ private function renderTypoScriptLog(): string diff --git a/typo3/sysext/adminpanel/Classes/Repositories/FrontendGroupsRepository.php b/typo3/sysext/adminpanel/Classes/Repositories/FrontendGroupsRepository.php index 35881d2bce92..6f184017356a 100644 --- a/typo3/sysext/adminpanel/Classes/Repositories/FrontendGroupsRepository.php +++ b/typo3/sysext/adminpanel/Classes/Repositories/FrontendGroupsRepository.php @@ -1,5 +1,5 @@ <?php -declare(strict_types=1); +declare(strict_types = 1); namespace TYPO3\CMS\Adminpanel\Repositories; @@ -110,7 +110,7 @@ class FrontendGroupsRepository /** * Returns the current BE user. * - * @return \TYPO3\CMS\Backend\FrontendBackendUserAuthentication + * @return FrontendBackendUserAuthentication */ protected function getBackendUser(): FrontendBackendUserAuthentication { diff --git a/typo3/sysext/adminpanel/Classes/Service/EditToolbarService.php b/typo3/sysext/adminpanel/Classes/Service/EditToolbarService.php new file mode 100644 index 000000000000..7ccb11944841 --- /dev/null +++ b/typo3/sysext/adminpanel/Classes/Service/EditToolbarService.php @@ -0,0 +1,273 @@ +<?php +declare(strict_types = 1); + +namespace TYPO3\CMS\Adminpanel\Service; + +use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; +use TYPO3\CMS\Backend\Routing\UriBuilder; +use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Database\ConnectionPool; +use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer; +use TYPO3\CMS\Core\Imaging\Icon; +use TYPO3\CMS\Core\Imaging\IconFactory; +use TYPO3\CMS\Core\Localization\LanguageService; +use TYPO3\CMS\Core\Type\Bitmask\Permission; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +/** + * Class for the Edit Toolbar + * + * @internal + */ +class EditToolbarService +{ + + /** + * Creates the tool bar links for the "edit" section of the Admin Panel. + * + * @return string A string containing images wrapped in <a>-tags linking them to proper functions. + */ + public function createToolbar(): string + { + $iconFactory = GeneralUtility::makeInstance(IconFactory::class); + $tsfe = $this->getTypoScriptFrontendController(); + // If mod.newContentElementWizard.override is set, use that extension's create new content wizard instead: + $tsConfig = BackendUtility::getModTSconfig($tsfe->page['uid'], 'mod'); + $moduleName = $tsConfig['properties']['newContentElementWizard.']['override'] ?? 'new_content_element'; + /** @var UriBuilder $uriBuilder */ + $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class); + $perms = $this->getBackendUser()->calcPerms($tsfe->page); + $langAllowed = $this->getBackendUser()->checkLanguageAccess($tsfe->sys_language_uid); + $id = $tsfe->id; + $returnUrl = GeneralUtility::getIndpEnv('REQUEST_URI'); + $classes = 'typo3-adminPanel-btn typo3-adminPanel-btn-default'; + $output = []; + $output[] = '<div class="typo3-adminPanel-form-group">'; + $output[] = ' <div class="typo3-adminPanel-btn-group" role="group">'; + + // History + /** @var UriBuilder $uriBuilder */ + $link = (string)$uriBuilder->buildUriFromRoute( + 'record_history', + [ + 'element' => 'pages:' . $id, + 'returnUrl' => $returnUrl, + ] + ); + $title = $this->extGetLL('edit_recordHistory'); + $output[] = '<a class="' . + $classes . + '" href="' . + htmlspecialchars($link, ENT_QUOTES | ENT_HTML5) . + '#latest" title="' . + $title . + '">'; + $output[] = ' ' . $iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL)->render(); + $output[] = '</a>'; + + // New Content + if ($perms & Permission::CONTENT_EDIT && $langAllowed) { + $linkParameters = [ + 'id' => $id, + 'returnUrl' => $returnUrl, + ]; + if (!empty($tsfe->sys_language_uid)) { + $linkParameters['sys_language_uid'] = $tsfe->sys_language_uid; + } + $link = (string)$uriBuilder->buildUriFromRoute($moduleName, $linkParameters); + $icon = $iconFactory->getIcon('actions-add', Icon::SIZE_SMALL)->render(); + $title = $this->extGetLL('edit_newContentElement'); + $output[] = '<a class="' . + $classes . + '" href="' . + htmlspecialchars($link, ENT_QUOTES | ENT_HTML5) . + '" title="' . + $title . + '">'; + $output[] = ' ' . $icon; + $output[] = '</a>'; + } + + // Move Page + if ($perms & Permission::PAGE_EDIT) { + $link = (string)$uriBuilder->buildUriFromRoute( + 'move_element', + [ + 'table' => 'pages', + 'uid' => $id, + 'returnUrl' => $returnUrl, + ] + ); + $icon = $iconFactory->getIcon('actions-document-move', Icon::SIZE_SMALL)->render(); + $title = $this->extGetLL('edit_move_page'); + $output[] = '<a class="' . + $classes . + '" href="' . + htmlspecialchars($link, ENT_QUOTES | ENT_HTML5) . + '" title="' . + $title . + '">'; + $output[] = ' ' . $icon; + $output[] = '</a>'; + } + + // New Page + if ($perms & Permission::PAGE_NEW) { + $link = (string)$uriBuilder->buildUriFromRoute( + 'db_new', + [ + 'id' => $id, + 'pagesOnly' => 1, + 'returnUrl' => $returnUrl, + ] + ); + $icon = $iconFactory->getIcon('actions-page-new', Icon::SIZE_SMALL)->render(); + $title = $this->extGetLL('edit_newPage'); + $output[] = '<a class="' . + $classes . + '" href="' . + htmlspecialchars($link, ENT_QUOTES | ENT_HTML5) . + '" title="' . + $title . + '">'; + $output[] = ' ' . $icon; + $output[] = '</a>'; + } + + // Edit Page + if ($perms & Permission::PAGE_EDIT) { + $link = (string)$uriBuilder->buildUriFromRoute( + 'record_edit', + [ + 'edit[pages][' . $id . ']' => 'edit', + 'noView' => 1, + 'returnUrl' => $returnUrl, + ] + ); + $icon = $iconFactory->getIcon('actions-page-open', Icon::SIZE_SMALL)->render(); + $title = $this->extGetLL('edit_editPageProperties'); + $output[] = '<a class="' . + $classes . + '" href="' . + htmlspecialchars($link, ENT_QUOTES | ENT_HTML5) . + '" title="' . + $title . + '">'; + $output[] = ' ' . $icon; + $output[] = '</a>'; + } + + // Edit Page Overlay + if ($perms & Permission::PAGE_EDIT && $tsfe->sys_language_uid && $langAllowed) { + $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) + ->getQueryBuilderForTable('pages'); + $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); + $row = $queryBuilder + ->select('uid', 'pid', 't3ver_state') + ->from('pages') + ->where( + $queryBuilder->expr()->eq( + $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'], + $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT) + ), + $queryBuilder->expr()->eq( + $GLOBALS['TCA']['pages']['ctrl']['languageField'], + $queryBuilder->createNamedParameter($tsfe->sys_language_uid, \PDO::PARAM_INT) + ) + ) + ->setMaxResults(1) + ->execute() + ->fetch(); + $tsfe->sys_page->versionOL('pages', $row); + if (is_array($row)) { + $link = (string)$uriBuilder->buildUriFromRoute( + 'record_edit', + [ + 'edit[pages][' . $row['uid'] . ']' => 'edit', + 'noView' => 1, + 'returnUrl' => $returnUrl, + ] + ); + $icon = $iconFactory->getIcon('mimetypes-x-content-page-language-overlay', Icon::SIZE_SMALL) + ->render(); + $title = $this->extGetLL('edit_editPageOverlay'); + $output[] = '<a class="' . + $classes . + '" href="' . + htmlspecialchars($link, ENT_QUOTES | ENT_HTML5) . + '" title="' . + $title . + '">'; + $output[] = ' ' . $icon; + $output[] = '</a>'; + } + } + + // Open list view + if ($this->getBackendUser()->check('modules', 'web_list')) { + $link = (string)$uriBuilder->buildUriFromRoute( + 'web_list', + [ + 'id' => $id, + 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI'), + ] + ); + $icon = $iconFactory->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render(); + $title = $this->extGetLL('edit_db_list'); + $output[] = '<a class="' . + $classes . + '" href="' . + htmlspecialchars($link, ENT_QUOTES | ENT_HTML5) . + '" title="' . + $title . + '">'; + $output[] = ' ' . $icon; + $output[] = '</a>'; + } + + $output[] = ' </div>'; + $output[] = '</div>'; + return implode('', $output); + } + + /** + * Translate given key + * + * @param string $key Key for a label in the $LOCAL_LANG array of "sysext/lang/Resources/Private/Language/locallang_tsfe.xlf + * @param bool $convertWithHtmlspecialchars If TRUE the language-label will be sent through htmlspecialchars + * @return string The value for the $key + */ + protected function extGetLL($key, $convertWithHtmlspecialchars = true): ?string + { + $labelStr = $this->getLanguageService()->getLL($key); + if ($convertWithHtmlspecialchars) { + $labelStr = htmlspecialchars($labelStr, ENT_QUOTES | ENT_HTML5); + } + return $labelStr; + } + + /** + * @return FrontendBackendUserAuthentication + */ + protected function getBackendUser(): FrontendBackendUserAuthentication + { + return $GLOBALS['BE_USER']; + } + + /** + * @return LanguageService + */ + protected function getLanguageService(): LanguageService + { + return $GLOBALS['LANG']; + } + + /** + * @return TypoScriptFrontendController + */ + protected function getTypoScriptFrontendController(): TypoScriptFrontendController + { + return $GLOBALS['TSFE']; + } +} diff --git a/typo3/sysext/adminpanel/Classes/View/AdminPanelView.php b/typo3/sysext/adminpanel/Classes/View/AdminPanelView.php index 1cc0a165aaae..cddd787b39ec 100644 --- a/typo3/sysext/adminpanel/Classes/View/AdminPanelView.php +++ b/typo3/sysext/adminpanel/Classes/View/AdminPanelView.php @@ -16,19 +16,16 @@ namespace TYPO3\CMS\Adminpanel\View; */ use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface; -use TYPO3\CMS\Backend\Utility\BackendUtility; -use TYPO3\CMS\Core\Cache\CacheManager; -use TYPO3\CMS\Core\Database\ConnectionPool; -use TYPO3\CMS\Core\Database\Query\Restriction\FrontendRestrictionContainer; +use TYPO3\CMS\Adminpanel\Service\EditToolbarService; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; -use TYPO3\CMS\Core\Service\DependencyOrderingService; -use TYPO3\CMS\Core\Type\Bitmask\Permission; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\PathUtility; /** * View class for the admin panel in frontend editing. + * + * @internal */ class AdminPanelView { @@ -63,28 +60,28 @@ class AdminPanelView */ protected $modules = []; + /** + * @var array + */ + protected $configuration; + /** * Constructor */ public function __construct() { - $this->initialize(); + $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); } /** - * Initializes settings for the admin panel. + * Setter for injecting new-style modules + * + * @see \TYPO3\CMS\Adminpanel\Controller\MainController::render() + * @param array $modules */ - public function initialize() + public function setModules(array $modules): void { - $this->validateSortAndInitializeModules(); - $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class); - $this->saveConfiguration(); - - foreach ($this->modules as $module) { - if ($module->isEnabled()) { - $module->initializeModule(); - } - } + $this->modules = $modules; } /** @@ -106,7 +103,7 @@ class AdminPanelView /** * Render a single module with header panel * - * @param \TYPO3\CMS\Frontend\AdminPanel\AdminPanelModuleInterface $module + * @param \TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface $module * @return string */ protected function getModule(AdminPanelModuleInterface $module): string @@ -316,80 +313,6 @@ class AdminPanelView return $this->getBackendUser()->uc['TSFE_adminConfig']['display_top'] ?? false; } - /** - * Save admin panel configuration to backend user UC - */ - protected function saveConfiguration() - { - $input = GeneralUtility::_GP('TSFE_ADMIN_PANEL'); - $beUser = $this->getBackendUser(); - if (is_array($input)) { - // Setting - $beUser->uc['TSFE_adminConfig'] = array_merge( - !is_array($beUser->uc['TSFE_adminConfig']) ? [] : $beUser->uc['TSFE_adminConfig'], - $input - ); - unset($beUser->uc['TSFE_adminConfig']['action']); - - foreach ($this->modules as $module) { - if ($module->isEnabled() && $module->isOpen()) { - $module->onSubmit($input); - } - } - // Saving - $beUser->writeUC(); - // Flush fluid template cache - $cacheManager = new CacheManager(); - $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']); - $cacheManager->getCache('fluid_template')->flush(); - } - } - - /** - * Validates, sorts and initiates the registered modules - * - * @throws \RuntimeException - */ - protected function validateSortAndInitializeModules(): void - { - $modules = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? []; - if (empty($modules)) { - return; - } - foreach ($modules as $identifier => $configuration) { - if (empty($configuration) || !is_array($configuration)) { - throw new \RuntimeException( - 'Missing configuration for module "' . $identifier . '".', - 1519490105 - ); - } - if (!is_string($configuration['module']) || - empty($configuration['module']) || - !class_exists($configuration['module']) || - !is_subclass_of( - $configuration['module'], - AdminPanelModuleInterface::class - )) { - throw new \RuntimeException( - 'The module "' . - $identifier . - '" defines an invalid module class. Ensure the class exists and implements the "' . - AdminPanelModuleInterface::class . - '".', - 1519490112 - ); - } - } - - $orderedModules = GeneralUtility::makeInstance(DependencyOrderingService::class)->orderByDependencies( - $modules - ); - - foreach ($orderedModules as $module) { - $this->modules[] = GeneralUtility::makeInstance($module['module']); - } - } - /***************************************************** * Admin Panel Layout Helper functions ****************************************************/ @@ -397,7 +320,7 @@ class AdminPanelView /** * Wraps a string in a link which will open/close a certain part of the Admin Panel * - * @param \TYPO3\CMS\Frontend\AdminPanel\AdminPanelModuleInterface $module + * @param AdminPanelModuleInterface $module * @return string */ protected function getSectionOpenerLink(AdminPanelModuleInterface $module): string @@ -426,164 +349,14 @@ class AdminPanelView /** * Creates the tool bar links for the "edit" section of the Admin Panel. * + * @deprecated * @return string A string containing images wrapped in <a>-tags linking them to proper functions. */ public function ext_makeToolBar() { - $tsfe = $this->getTypoScriptFrontendController(); - // If mod.newContentElementWizard.override is set, use that extension's create new content wizard instead: - $tsConfig = BackendUtility::getModTSconfig($tsfe->page['uid'], 'mod'); - $moduleName = $tsConfig['properties']['newContentElementWizard.']['override'] ?? 'new_content_element'; - /** @var \TYPO3\CMS\Backend\Routing\UriBuilder $uriBuilder */ - $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class); - $perms = $this->getBackendUser()->calcPerms($tsfe->page); - $langAllowed = $this->getBackendUser()->checkLanguageAccess($tsfe->sys_language_uid); - $id = $tsfe->id; - $returnUrl = GeneralUtility::getIndpEnv('REQUEST_URI'); - $classes = 'typo3-adminPanel-btn typo3-adminPanel-btn-default'; - $output = []; - $output[] = '<div class="typo3-adminPanel-form-group">'; - $output[] = ' <div class="typo3-adminPanel-btn-group" role="group">'; - - // History - $link = (string)$uriBuilder->buildUriFromRoute( - 'record_history', - [ - 'element' => 'pages:' . $id, - 'returnUrl' => $returnUrl - ] - ); - $title = $this->extGetLL('edit_recordHistory'); - $output[] = '<a class="' . $classes . '" href="' . htmlspecialchars($link) . '#latest" title="' . $title . '">'; - $output[] = ' ' . $this->iconFactory->getIcon('actions-document-history-open', Icon::SIZE_SMALL)->render(); - $output[] = '</a>'; - - // New Content - if ($perms & Permission::CONTENT_EDIT && $langAllowed) { - $linkParameters = [ - 'id' => $id, - 'returnUrl' => $returnUrl, - ]; - if (!empty($tsfe->sys_language_uid)) { - $linkParameters['sys_language_uid'] = $tsfe->sys_language_uid; - } - $link = (string)$uriBuilder->buildUriFromRoute($moduleName, $linkParameters); - $icon = $this->iconFactory->getIcon('actions-add', Icon::SIZE_SMALL)->render(); - $title = $this->extGetLL('edit_newContentElement'); - $output[] = '<a class="' . $classes . '" href="' . htmlspecialchars($link) . '" title="' . $title . '">'; - $output[] = ' ' . $icon; - $output[] = '</a>'; - } - - // Move Page - if ($perms & Permission::PAGE_EDIT) { - $link = (string)$uriBuilder->buildUriFromRoute( - 'move_element', - [ - 'table' => 'pages', - 'uid' => $id, - 'returnUrl' => $returnUrl - ] - ); - $icon = $this->iconFactory->getIcon('actions-document-move', Icon::SIZE_SMALL)->render(); - $title = $this->extGetLL('edit_move_page'); - $output[] = '<a class="' . $classes . '" href="' . htmlspecialchars($link) . '" title="' . $title . '">'; - $output[] = ' ' . $icon; - $output[] = '</a>'; - } - - // New Page - if ($perms & Permission::PAGE_NEW) { - $link = (string)$uriBuilder->buildUriFromRoute( - 'db_new', - [ - 'id' => $id, - 'pagesOnly' => 1, - 'returnUrl' => $returnUrl - ] - ); - $icon = $this->iconFactory->getIcon('actions-page-new', Icon::SIZE_SMALL)->render(); - $title = $this->extGetLL('edit_newPage'); - $output[] = '<a class="' . $classes . '" href="' . htmlspecialchars($link) . '" title="' . $title . '">'; - $output[] = ' ' . $icon; - $output[] = '</a>'; - } - - // Edit Page - if ($perms & Permission::PAGE_EDIT) { - $link = (string)$uriBuilder->buildUriFromRoute( - 'record_edit', - [ - 'edit[pages][' . $id . ']' => 'edit', - 'noView' => 1, - 'returnUrl' => $returnUrl - ] - ); - $icon = $this->iconFactory->getIcon('actions-page-open', Icon::SIZE_SMALL)->render(); - $title = $this->extGetLL('edit_editPageProperties'); - $output[] = '<a class="' . $classes . '" href="' . htmlspecialchars($link) . '" title="' . $title . '">'; - $output[] = ' ' . $icon; - $output[] = '</a>'; - } - - // Edit Page Overlay - if ($perms & Permission::PAGE_EDIT && $tsfe->sys_language_uid && $langAllowed) { - $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) - ->getQueryBuilderForTable('pages'); - $queryBuilder->setRestrictions(GeneralUtility::makeInstance(FrontendRestrictionContainer::class)); - $row = $queryBuilder - ->select('uid', 'pid', 't3ver_state') - ->from('pages') - ->where( - $queryBuilder->expr()->eq( - $GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'], - $queryBuilder->createNamedParameter($id, \PDO::PARAM_INT) - ), - $queryBuilder->expr()->eq( - $GLOBALS['TCA']['pages']['ctrl']['languageField'], - $queryBuilder->createNamedParameter($tsfe->sys_language_uid, \PDO::PARAM_INT) - ) - ) - ->setMaxResults(1) - ->execute() - ->fetch(); - $tsfe->sys_page->versionOL('pages', $row); - if (is_array($row)) { - $link = (string)$uriBuilder->buildUriFromRoute( - 'record_edit', - [ - 'edit[pages][' . $row['uid'] . ']' => 'edit', - 'noView' => 1, - 'returnUrl' => $returnUrl - ] - ); - $icon = $this->iconFactory->getIcon('mimetypes-x-content-page-language-overlay', Icon::SIZE_SMALL)->render(); - $title = $this->extGetLL('edit_editPageOverlay'); - $output[] = '<a class="' . $classes . '" href="' . htmlspecialchars($link) . '" title="' . $title . '">'; - $output[] = ' ' . $icon; - $output[] = '</a>'; - } - } - - // Open list view - if ($this->getBackendUser()->check('modules', 'web_list')) { - $link = (string)$uriBuilder->buildUriFromRoute( - 'web_list', - [ - 'id' => $id, - 'returnUrl' => GeneralUtility::getIndpEnv('REQUEST_URI') - ] - ); - $icon = $this->iconFactory->getIcon('actions-system-list-open', Icon::SIZE_SMALL)->render(); - $title = $this->extGetLL('edit_db_list'); - $output[] = '<a class="' . $classes . '" href="' . htmlspecialchars($link) . '" title="' . $title . '">'; - $output[] = ' ' . $icon; - $output[] = '</a>'; - } - - $output[] = ' </div>'; - $output[] = '</div>'; - return implode('', $output); + trigger_error('', E_USER_DEPRECATED); + $editToolbarService = GeneralUtility::makeInstance(EditToolbarService::class); + return $editToolbarService->createToolbar(); } /** @@ -662,9 +435,9 @@ class AdminPanelView // Returns TRUE if the module checked is "preview" and the forcePreview flag is set. if ($key === 'preview' && $this->ext_forcePreview) { $result = true; - } elseif (!empty($this->getBackendUser()->extAdminConfig['enable.']['all'])) { + } elseif (!empty($this->configuration['enable.']['all'])) { $result = true; - } elseif (!empty($this->getBackendUser()->extAdminConfig['enable.'][$key])) { + } elseif (!empty($this->configuration['enable.'][$key])) { $result = true; } return $result; @@ -707,20 +480,20 @@ class AdminPanelView // deprecated if ( $sectionName === 'edit' && ( - $val === 'displayIcons' && $beUser->extAdminConfig['module.']['edit.']['forceDisplayIcons'] || - $val === 'displayFieldIcons' && $beUser->extAdminConfig['module.']['edit.']['forceDisplayFieldIcons'] || - $val === 'editNoPopup' && $beUser->extAdminConfig['module.']['edit.']['forceNoPopup'] + $val === 'displayIcons' && $this->configuration['module.']['edit.']['forceDisplayIcons'] || + $val === 'displayFieldIcons' && $this->configuration['module.']['edit.']['forceDisplayFieldIcons'] || + $val === 'editNoPopup' && $this->configuration['module.']['edit.']['forceNoPopup'] ) ) { return true; } // Override all settings with user TSconfig - if ($val && isset($beUser->extAdminConfig['override.'][$sectionName . '.'][$val])) { - return $beUser->extAdminConfig['override.'][$sectionName . '.'][$val]; + if ($val && isset($this->configuration['override.'][$sectionName . '.'][$val])) { + return $this->configuration['override.'][$sectionName . '.'][$val]; } - if (!$val && isset($beUser->extAdminConfig['override.'][$sectionName])) { - return $beUser->extAdminConfig['override.'][$sectionName]; + if (!$val && isset($this->configuration['override.'][$sectionName])) { + return $this->configuration['override.'][$sectionName]; } $returnValue = $val ? $beUser->uc['TSFE_adminConfig'][$sectionName . '_' . $val] : 1; diff --git a/typo3/sysext/adminpanel/Configuration/RequestMiddlewares.php b/typo3/sysext/adminpanel/Configuration/RequestMiddlewares.php new file mode 100644 index 000000000000..ffa8eb191e7e --- /dev/null +++ b/typo3/sysext/adminpanel/Configuration/RequestMiddlewares.php @@ -0,0 +1,22 @@ +<?php +/** + * An array consisting of implementations of middlewares for a middleware stack to be registered + * 'stackname' => [ + * 'middleware-identifier' => [ + * 'target' => classname or callable + * 'before/after' => array of dependencies + * ] + * ] + */ +return [ + 'frontend' => [ + 'typo3/cms-adminpanel/initiator' => [ + 'target' => \TYPO3\CMS\Adminpanel\Middleware\AdminPanelInitiator::class, + 'after' => [ + 'typo3/cms-frontend/tsfe', + 'typo3/cms-frontend/authentication', + 'typo3/cms-frontend/backend-user-authentication', + ] + ], + ] +]; diff --git a/typo3/sysext/adminpanel/Tests/Unit/View/AdminPanelViewTest.php b/typo3/sysext/adminpanel/Tests/Unit/View/AdminPanelViewTest.php deleted file mode 100644 index bfd416b6fc2a..000000000000 --- a/typo3/sysext/adminpanel/Tests/Unit/View/AdminPanelViewTest.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php -declare(strict_types=1); - -namespace TYPO3\CMS\Adminpanel\Tests\Unit\View; - -/* - * 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\CMS\Adminpanel\Tests\Unit\View\Fixtures\AdminPanelDisabledModuleFixture; -use TYPO3\CMS\Adminpanel\Tests\Unit\View\Fixtures\AdminPanelEnabledShownOnSubmitInitializeModuleFixture; -use TYPO3\CMS\Adminpanel\View\AdminPanelView; -use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; -use TYPO3\CMS\Core\Imaging\IconFactory; -use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\TestingFramework\Core\Unit\UnitTestCase; - -/** - * Test case - */ -class AdminPanelViewTest extends UnitTestCase -{ - public function setUp() - { - parent::setUp(); - $iconFactoryProphecy = $this->prophesize(IconFactory::class); - GeneralUtility::addInstance(IconFactory::class, $iconFactoryProphecy->reveal()); - $beUserProphecy = $this->prophesize(BackendUserAuthentication::class); - $GLOBALS['BE_USER'] = $beUserProphecy->reveal(); - } - - /** - * @test - */ - public function initializeCallsOnSubmitIfInputVarsAreSet() - { - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] = [ - 'fixtureOnSubmit' => [ - 'module' => AdminPanelEnabledShownOnSubmitInitializeModuleFixture::class, - ], - ]; - - $postVars = ['preview_showFluidDebug' => '1']; - $_GET['TSFE_ADMIN_PANEL'] = $postVars; - - $this->expectExceptionCode('1519997815'); - - new AdminPanelView(); - } - - /** - * @test - */ - public function initializeCallsInitializeModulesForEnabledModules() - { - $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] = [ - 'enabledModule' => [ - 'module' => AdminPanelEnabledShownOnSubmitInitializeModuleFixture::class, - ], - 'disabledModule' => [ - 'module' => AdminPanelDisabledModuleFixture::class, - 'before' => ['enabledModule'], - ], - ]; - - $this->expectExceptionCode(1519999273); - new AdminPanelView(); - } -} diff --git a/typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelDisabledModuleFixture.php b/typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelDisabledModuleFixture.php deleted file mode 100644 index d9cc6741904a..000000000000 --- a/typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelDisabledModuleFixture.php +++ /dev/null @@ -1,141 +0,0 @@ -<?php -declare(strict_types=1); -namespace TYPO3\CMS\Adminpanel\Tests\Unit\View\Fixtures; - -/* - * 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\CMS\Adminpanel\Modules\AdminPanelModuleInterface; - -class AdminPanelDisabledModuleFixture implements AdminPanelModuleInterface -{ - - /** - * Additional JavaScript code for this module - * (you should only use vanilla JS here, as you cannot - * rely on the web site providing a specific framework) - * - * @return string - */ - public function getAdditionalJavaScriptCode(): string - { - return ''; - } - - /** - * Module content as rendered HTML - * - * @return string - */ - public function getContent(): string - { - return ''; - } - - /** - * Identifier for this module, - * for example "preview" or "cache" - * - * @return string - */ - public function getIdentifier(): string - { - return ''; - } - - /** - * Module label - * - * @return string - */ - public function getLabel(): string - { - return ''; - } - - /** - * Initialize the module - runs early in a TYPO3 request - */ - public function initializeModule(): void - { - throw new \RuntimeException('I should not be initialized.', 1519999375); - } - - /** - * Module is enabled - * -> should be initialized - * A module may be enabled but not shown - * -> only the initializeModule() method - * will be called - * - * @return bool - */ - public function isEnabled(): bool - { - return false; - } - - /** - * Module is open - * -> module is enabled - * -> module panel is shown and open - * - * @return bool - */ - public function isOpen(): bool - { - return true; - } - - /** - * Module is shown - * -> module is enabled - * -> module panel should be displayed - * - * @return bool - */ - public function isShown(): bool - { - return true; - } - - /** - * Executed on saving / submit of the configuration form - * Can be used to react to changed settings - * (for example: clearing a specific cache) - * - * @param array $input - */ - public function onSubmit(array $input): void - { - } - - /** - * Does this module need a form submit? - * - * @return bool - */ - public function showFormSubmitButton(): bool - { - return true; - } - - /** - * Returns a string array with javascript files that will be rendered after the module - * - * @return array - */ - public function getJavaScriptFiles(): array - { - return []; - } -} diff --git a/typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelEnabledShownOnSubmitInitializeModuleFixture.php b/typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelEnabledShownOnSubmitInitializeModuleFixture.php deleted file mode 100644 index 0835228afb74..000000000000 --- a/typo3/sysext/adminpanel/Tests/Unit/View/Fixtures/AdminPanelEnabledShownOnSubmitInitializeModuleFixture.php +++ /dev/null @@ -1,142 +0,0 @@ -<?php -declare(strict_types=1); -namespace TYPO3\CMS\Adminpanel\Tests\Unit\View\Fixtures; - -/* - * 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\CMS\Adminpanel\Modules\AdminPanelModuleInterface; - -class AdminPanelEnabledShownOnSubmitInitializeModuleFixture implements AdminPanelModuleInterface -{ - - /** - * Additional JavaScript code for this module - * (you should only use vanilla JS here, as you cannot - * rely on the web site providing a specific framework) - * - * @return string - */ - public function getAdditionalJavaScriptCode(): string - { - return ''; - } - - /** - * Module content as rendered HTML - * - * @return string - */ - public function getContent(): string - { - return ''; - } - - /** - * Identifier for this module, - * for example "preview" or "cache" - * - * @return string - */ - public function getIdentifier(): string - { - return ''; - } - - /** - * Module label - * - * @return string - */ - public function getLabel(): string - { - return ''; - } - - /** - * Initialize the module - runs early in a TYPO3 request - */ - public function initializeModule(): void - { - throw new \RuntimeException('initialized.', 1519999273); - } - - /** - * Module is enabled - * -> should be initialized - * A module may be enabled but not shown - * -> only the initializeModule() method - * will be called - * - * @return bool - */ - public function isEnabled(): bool - { - return true; - } - - /** - * Module is open - * -> module is enabled - * -> module panel is shown and open - * - * @return bool - */ - public function isOpen(): bool - { - return true; - } - - /** - * Module is shown - * -> module is enabled - * -> module panel should be displayed - * - * @return bool - */ - public function isShown(): bool - { - return true; - } - - /** - * Executed on saving / submit of the configuration form - * Can be used to react to changed settings - * (for example: clearing a specific cache) - * - * @param array $input - */ - public function onSubmit(array $input): void - { - throw new \RuntimeException('Catch me if you can!', 1519997815); - } - - /** - * Does this module need a form submit? - * - * @return bool - */ - public function showFormSubmitButton(): bool - { - return true; - } - - /** - * Returns a string array with javascript files that will be rendered after the module - * - * @return array - */ - public function getJavaScriptFiles(): array - { - return []; - } -} diff --git a/typo3/sysext/adminpanel/composer.json b/typo3/sysext/adminpanel/composer.json index 15c401cee7ae..5fe988055c64 100644 --- a/typo3/sysext/adminpanel/composer.json +++ b/typo3/sysext/adminpanel/composer.json @@ -13,8 +13,13 @@ "sort-packages": true }, "require": { + "typo3/cms-backend": "9.2.*@dev", "typo3/cms-core": "9.2.*@dev", - "typo3/cms-frontend": "9.2.*@dev" + "typo3/cms-fluid": "9.2.*@dev", + "typo3/cms-frontend": "9.2.*@dev", + "psr/http-message": "~1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0" }, "conflict": { "typo3/cms": "*" diff --git a/typo3/sysext/adminpanel/ext_localconf.php b/typo3/sysext/adminpanel/ext_localconf.php index 0094d2f69a00..ba181f018207 100644 --- a/typo3/sysext/adminpanel/ext_localconf.php +++ b/typo3/sysext/adminpanel/ext_localconf.php @@ -1,4 +1,7 @@ <?php +defined('TYPO3_MODE') or die(); + +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['contentPostProc-output'][] = \TYPO3\CMS\Adminpanel\Hooks\RenderHook::class . '->renderAdminPanel'; $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] = [ 'preview' => [ diff --git a/typo3/sysext/backend/Classes/FrontendBackendUserAuthentication.php b/typo3/sysext/backend/Classes/FrontendBackendUserAuthentication.php index cd087423327c..6c24767ccf2b 100644 --- a/typo3/sysext/backend/Classes/FrontendBackendUserAuthentication.php +++ b/typo3/sysext/backend/Classes/FrontendBackendUserAuthentication.php @@ -15,6 +15,7 @@ namespace TYPO3\CMS\Backend; */ use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; +use TYPO3\CMS\Core\Compatibility\PublicPropertyDeprecationTrait; use TYPO3\CMS\Core\Database\ConnectionPool; use TYPO3\CMS\Core\Database\Query\QueryBuilder; use TYPO3\CMS\Core\Database\Query\QueryHelper; @@ -29,6 +30,19 @@ use TYPO3\CMS\Core\Utility\GeneralUtility; */ class FrontendBackendUserAuthentication extends BackendUserAuthentication { + use PublicPropertyDeprecationTrait; + + /** + * Properties which have been moved to protected status from public + * + * @var array + */ + protected $deprecatedPublicProperties = [ + 'extAdmEnabled' => 'Using $extAdmEnabled of class FrontendBackendUserAuthentication from the outside is discouraged, as this variable is only used for internal storage.', + 'adminPanel' => 'Using $adminPanel of class FrontendBackendUserAuthentication from the outside is discouraged, as this variable is only used for internal storage.', + 'extAdminConfig' => 'Using $extAdminConfig of class FrontendBackendUserAuthentication from the outside is discouraged, as this variable is only used for internal storage.', + ]; + /** * Form field with login name. * @@ -69,11 +83,13 @@ class FrontendBackendUserAuthentication extends BackendUserAuthentication * General flag which is set if the adminpanel is enabled at all. * * @var bool + * @deprecated since TYPO3v9, property will be removed in TYPO3 v10 - see extension "adminpanel" for new API */ public $extAdmEnabled = false; /** * @var \TYPO3\CMS\Adminpanel\View\AdminPanelView Instance of admin panel + * @deprecated since TYPO3v9, property will be removed in TYPO3 v10 - see extension "adminpanel" for new API */ public $adminPanel = null; @@ -84,58 +100,39 @@ class FrontendBackendUserAuthentication extends BackendUserAuthentication /** * @var array + * @deprecated since TYPO3v9, property will be removed in TYPO3 v10 - see extension "adminpanel" for new API */ public $extAdminConfig = []; /** * Initializes the admin panel. + * + * @deprecated since TYPO3v9 - rewritten as middleware */ public function initializeAdminPanel() { - $this->extAdminConfig = $this->getTSConfigProp('admPanel'); - if (isset($this->extAdminConfig['enable.'])) { - foreach ($this->extAdminConfig['enable.'] as $value) { - if ($value) { - $this->adminPanel = GeneralUtility::makeInstance(\TYPO3\CMS\Adminpanel\View\AdminPanelView::class); - $this->extAdmEnabled = true; - break; - } - } - } + trigger_error('Method will be removed in TYPO3 v10 - initialization is done via middleware.', E_USER_DEPRECATED); } /** * Initializes frontend editing. + * + * @deprecated since TYPO3v9 - rewritten as middleware */ public function initializeFrontendEdit() { - if (isset($this->extAdminConfig['enable.']) && $this->isFrontendEditingActive()) { - foreach ($this->extAdminConfig['enable.'] as $value) { - if ($value) { - if ($GLOBALS['TSFE'] instanceof \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController) { - // Grab the Page TSConfig property that determines which controller to use. - $pageTSConfig = $GLOBALS['TSFE']->getPagesTSconfig(); - $controllerKey = $pageTSConfig['TSFE.']['frontendEditingController'] ?? 'default'; - } else { - $controllerKey = 'default'; - } - $controllerClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController'][$controllerKey]; - if ($controllerClass) { - $this->frontendEdit = GeneralUtility::makeInstance($controllerClass); - } - break; - } - } - } + trigger_error('Method will be removed in TYPO3 v10 - initialization is done via middleware.', E_USER_DEPRECATED); } /** * Determines whether frontend editing is currently active. * + * @deprecated since TYPO3 v9 - see ext "feedit" for API * @return bool Whether frontend editing is active */ public function isFrontendEditingActive() { + trigger_error('Method will be removed in TYPO3 v10 - use underlying TSFE directly.', E_USER_DEPRECATED); return $this->extAdmEnabled && ( $this->adminPanel->isAdminModuleEnabled('edit') || (int)$GLOBALS['TSFE']->displayEditIcons === 1 || @@ -146,20 +143,24 @@ class FrontendBackendUserAuthentication extends BackendUserAuthentication /** * Delegates to the appropriate view and renders the admin panel content. * + * @deprecated since TYPO3v9 - see ext "adminpanel" for new API * @return string. */ public function displayAdminPanel() { + trigger_error('Method will be removed in TYPO3 v10 - use MainController of adminpanel extension.', E_USER_DEPRECATED); return $this->adminPanel->display(); } /** * Determines whether the admin panel is enabled and visible. * + * @deprecated since TYPO3v9 - see ext "adminpanel" for new API * @return bool true if the admin panel is enabled and visible */ public function isAdminPanelVisible() { + trigger_error('Method will be removed in TYPO3 v10 - use new adminpanel API instead.', E_USER_DEPRECATED); return $this->extAdmEnabled && !$this->extAdminConfig['hide'] && $GLOBALS['TSFE']->config['config']['admPanel']; } diff --git a/typo3/sysext/core/Documentation/Changelog/master/Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst new file mode 100644 index 000000000000..051f5ed17f8e --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst @@ -0,0 +1,53 @@ +.. include:: ../../Includes.txt + +=============================================================================================================== +Deprecation: #84641 - Deprecated AdminPanel related methods and properties in FrontendBackendUserAuthentication +=============================================================================================================== + +See :issue:`84641` + +Description +=========== + +The admin panel has been extracted into an own extension. To enable users to de-activate the admin panel completely, the hard coupling between the extension and other parts of the core had to be resolved. The admin panel now takes care of its own initialization and provides API methods related to its functionality. +The following API methods and properties located in `FrontendBackendUserAuthentication` have been deprecated: + +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::$adminPanel` +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::$extAdminConfig` +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::$extAdmEnabled` + +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::initializeAdminPanel()` +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::initializeFrontendEdit()` +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::isFrontendEditingActive()` +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::displayAdminPanel()` +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::isAdminPanelVisible()` + + +Impact +====== + +Using any of the methods will trigger a deprecation warning. + + +Affected Installations +====================== + +Any installation directly calling one of the mentioned methods or properties. + + +Migration +========= + +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::$adminPanel` - use `MainController` of adminpanel instead +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::$extAdminConfig` - load directly from TSConfig if needed +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::$extAdmEnabled` - check directly against TSConfig if necessary + +Both initialization methods `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::initializeAdminPanel` and +`\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::initializeFrontendEdit` were rewritten as PSR-15 middlewares, +remove any calls as they are not necessary anymore. + +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::isFrontendEditingActive` and `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::isAdminPanelVisible` - check against TSFE directly + +* `\TYPO3\CMS\Backend\FrontendBackendUserAuthentication::displayAdminPanel` - use `MainController::render()` instead + +.. index:: Frontend, PHP-API, PartiallyScanned diff --git a/typo3/sysext/feedit/Classes/FrontendEditPanel.php b/typo3/sysext/feedit/Classes/FrontendEditPanel.php index 54addc2f3ace..01331773c829 100644 --- a/typo3/sysext/feedit/Classes/FrontendEditPanel.php +++ b/typo3/sysext/feedit/Classes/FrontendEditPanel.php @@ -13,7 +13,7 @@ namespace TYPO3\CMS\Feedit; * * The TYPO3 project - inspiring people to share! */ -use TYPO3\CMS\Adminpanel\View\AdminPanelView; +use TYPO3\CMS\Adminpanel\Service\EditToolbarService; use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; use TYPO3\CMS\Core\Imaging\Icon; use TYPO3\CMS\Core\Imaging\IconFactory; @@ -97,8 +97,9 @@ class FrontendEditPanel $hideField = $GLOBALS['TCA'][$table]['ctrl']['enablecolumns']['disabled']; $panel = ''; - if (isset($allow['toolbar']) && $this->backendUser->adminPanel instanceof AdminPanelView) { - $panel .= $this->backendUser->adminPanel->ext_makeToolBar(); + if (isset($allow['toolbar'])) { + $editToolbarService = GeneralUtility::makeInstance(EditToolbarService::class); + $panel .= $editToolbarService->createToolbar(); } if (isset($allow['edit'])) { $icon = '<span title="' . $this->backendUser->extGetLL('p_editRecord') . '">' . $this->iconFactory->getIcon('actions-document-open', Icon::SIZE_SMALL)->render('inline') . '</span>'; diff --git a/typo3/sysext/feedit/Classes/Middleware/FrontendEditInitiator.php b/typo3/sysext/feedit/Classes/Middleware/FrontendEditInitiator.php new file mode 100644 index 000000000000..96c7ede4ec2d --- /dev/null +++ b/typo3/sysext/feedit/Classes/Middleware/FrontendEditInitiator.php @@ -0,0 +1,67 @@ +<?php +declare(strict_types = 1); + +namespace TYPO3\CMS\Feedit\Middleware; + +/* + * 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 Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\MiddlewareInterface; +use Psr\Http\Server\RequestHandlerInterface; +use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController; + +/** + * PSR-15 middleware initializing frontend editing + */ +class FrontendEditInitiator implements MiddlewareInterface +{ + + /** + * Process an incoming server request and return a response, optionally delegating + * response creation to a handler. + * + * @param ServerRequestInterface $request + * @param RequestHandlerInterface $handler + * @return ResponseInterface + */ + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface + { + if ($GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication) { + $config = $GLOBALS['BE_USER']->getTSConfigProp('admPanel'); + $active = (int)$GLOBALS['TSFE']->displayEditIcons === 1 || (int)$GLOBALS['TSFE']->displayFieldEditIcons === 1; + if ($active && isset($config['enable.'])) { + foreach ($config['enable.'] as $value) { + if ($value) { + if ($GLOBALS['TSFE'] instanceof TypoScriptFrontendController) { + // Grab the Page TSConfig property that determines which controller to use. + $pageTSConfig = $GLOBALS['TSFE']->getPagesTSconfig(); + $controllerKey = $pageTSConfig['TSFE.']['frontendEditingController'] ?? 'default'; + } else { + $controllerKey = 'default'; + } + $controllerClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController'][$controllerKey]; + if ($controllerClass) { + $GLOBALS['BE_USER']->frontendEdit = GeneralUtility::makeInstance($controllerClass); + } + break; + } + } + } + } + return $handler->handle($request); + } +} diff --git a/typo3/sysext/feedit/Configuration/RequestMiddlewares.php b/typo3/sysext/feedit/Configuration/RequestMiddlewares.php new file mode 100644 index 000000000000..71ca4acff442 --- /dev/null +++ b/typo3/sysext/feedit/Configuration/RequestMiddlewares.php @@ -0,0 +1,21 @@ +<?php +/** + * An array consisting of implementations of middlewares for a middleware stack to be registered + * 'stackname' => [ + * 'middleware-identifier' => [ + * 'target' => classname or callable + * 'before/after' => array of dependencies + * ] + * ] + */ +return [ + 'frontend' => [ + 'typo3/cms-frontendedit/initiator' => [ + 'target' => \TYPO3\CMS\Feedit\Middleware\FrontendEditInitiator::class, + 'after' => [ + 'typo3/cms-adminpanel/initiator', + 'typo3/cms-frontend/page-resolver', + ] + ], + ] +]; diff --git a/typo3/sysext/feedit/composer.json b/typo3/sysext/feedit/composer.json index 45608ec6d41b..05792433669a 100644 --- a/typo3/sysext/feedit/composer.json +++ b/typo3/sysext/feedit/composer.json @@ -13,7 +13,13 @@ "sort-packages": true }, "require": { - "typo3/cms-core": "9.2.*@dev" + "typo3/cms-adminpanel": "9.2.*@dev", + "typo3/cms-backend": "9.2.*@dev", + "typo3/cms-core": "9.2.*@dev", + "typo3/cms-frontend": "9.2.*@dev", + "psr/http-message": "~1.0", + "psr/http-server-handler": "^1.0", + "psr/http-server-middleware": "^1.0" }, "conflict": { "typo3/cms": "*" diff --git a/typo3/sysext/frontend/Classes/Http/RequestHandler.php b/typo3/sysext/frontend/Classes/Http/RequestHandler.php index c7755dab753a..e00620edc6d7 100644 --- a/typo3/sysext/frontend/Classes/Http/RequestHandler.php +++ b/typo3/sysext/frontend/Classes/Http/RequestHandler.php @@ -1,5 +1,6 @@ <?php declare(strict_types = 1); + namespace TYPO3\CMS\Frontend\Http; /* @@ -18,7 +19,6 @@ namespace TYPO3\CMS\Frontend\Http; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Server\RequestHandlerInterface as PsrRequestHandlerInterface; -use TYPO3\CMS\Backend\FrontendBackendUserAuthentication; use TYPO3\CMS\Core\FrontendEditing\FrontendEditingController; use TYPO3\CMS\Core\Http\NullResponse; use TYPO3\CMS\Core\Http\RequestHandlerInterface; @@ -161,11 +161,6 @@ class RequestHandler implements RequestHandlerInterface, PsrRequestHandlerInterf // Finish timetracking $this->timeTracker->pull(); - // Admin panel - if ($controller->isBackendUserLoggedIn() && $GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication && $GLOBALS['BE_USER']->isAdminPanelVisible()) { - $controller->content = str_ireplace('</body>', $GLOBALS['BE_USER']->displayAdminPanel() . '</body>', $controller->content); - } - if ($isOutputting) { $response->getBody()->write($controller->content); } diff --git a/typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php b/typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php index 9f64161c1871..161108564a1e 100644 --- a/typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php +++ b/typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php @@ -1,5 +1,6 @@ <?php declare(strict_types = 1); + namespace TYPO3\CMS\Frontend\Middleware; /* @@ -83,8 +84,6 @@ class BackendUserAuthenticator implements MiddlewareInterface Bootstrap::initializeLanguageObject(); Bootstrap::initializeBackendRouter(); Bootstrap::loadExtTables(); - // Initialize admin panel since simulation settings are required here - $GLOBALS['BE_USER']->initializeAdminPanel(); } return $handler->handle($request); diff --git a/typo3/sysext/frontend/composer.json b/typo3/sysext/frontend/composer.json index 133c0b6f13b4..107b11d351bb 100644 --- a/typo3/sysext/frontend/composer.json +++ b/typo3/sysext/frontend/composer.json @@ -18,6 +18,9 @@ "conflict": { "typo3/cms": "*" }, + "suggest": { + "typo3/cms-adminpanel": "Provides additional information and functionality for backend users in the frontend." + }, "replace": { "frontend": "*" }, diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php index d7b3831c7f73..4808ea525999 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php @@ -2081,4 +2081,39 @@ return [ 'Deprecation-84637-TemplateService-linkDataFunctionalityMovedInPageLinkBuilder.rst', ], ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->initializeAdminPanel' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->initializeFrontendEdit' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->isFrontendEditingActive' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->displayAdminPanel' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->isAdminPanelVisible' => [ + 'numberOfMandatoryArguments' => 0, + 'maximumNumberOfArguments' => 0, + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], ]; diff --git a/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php b/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php index 78773493584b..b24c1ddde8fb 100644 --- a/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php +++ b/typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php @@ -376,4 +376,19 @@ return [ 'Deprecation-84295-UseServerRequestInterfaceInFileEditFileController.rst', ], ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->adminPanel' => [ + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->extAdminConfig' => [ + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], + 'TYPO3\CMS\Backend\FrontendBackendUserAuthentication->extAdmEnabled' => [ + 'restFiles' => [ + 'Deprecation-84641-DeprecatedAdminPanelRelatedMethods.rst', + ], + ], ]; diff --git a/typo3/sysext/lang/Resources/Private/Language/locallang_tsfe.xlf b/typo3/sysext/lang/Resources/Private/Language/locallang_tsfe.xlf index a9652af87212..5bb39197cd3e 100644 --- a/typo3/sysext/lang/Resources/Private/Language/locallang_tsfe.xlf +++ b/typo3/sysext/lang/Resources/Private/Language/locallang_tsfe.xlf @@ -9,6 +9,9 @@ <trans-unit id="adminPanelTitle"> <source>TYPO3 ADMIN PANEL</source> </trans-unit> + <trans-unit id="preview"> + <source>Preview</source> + </trans-unit> <trans-unit id="publish"> <source>Publish</source> </trans-unit> diff --git a/typo3/sysext/workspaces/Classes/Authentication/PreviewUserAuthentication.php b/typo3/sysext/workspaces/Classes/Authentication/PreviewUserAuthentication.php index 2ddc33e96f76..807a18ee77b4 100644 --- a/typo3/sysext/workspaces/Classes/Authentication/PreviewUserAuthentication.php +++ b/typo3/sysext/workspaces/Classes/Authentication/PreviewUserAuthentication.php @@ -1,5 +1,6 @@ <?php declare(strict_types = 1); + namespace TYPO3\CMS\Workspaces\Authentication; /* @@ -107,34 +108,4 @@ class PreviewUserAuthentication extends BackendUserAuthentication { return Permission::PAGE_SHOW; } - - /** - * Stub to ensure that frontend editing is not possible as a preview user - * - * @return bool - */ - public function initializeFrontendEdit() - { - return false; - } - - /** - * Stub to ensure that frontend editing is not possible as a preview user - * - * @return bool - */ - public function isFrontendEditingActive() - { - return false; - } - - /** - * Stub to ensure that admin panel is not visible as a preview user - * - * @return bool - */ - public function isAdminPanelVisible() - { - return false; - } } -- GitLab