[FEATURE] Add SQL Logging to AdminPanel
[Packages/TYPO3.CMS.git] / typo3 / sysext / adminpanel / Classes / Controller / MainController.php
index 2df560c..b347901 100644 (file)
@@ -16,16 +16,17 @@ namespace TYPO3\CMS\Adminpanel\Controller;
  * The TYPO3 project - inspiring people to share!
  */
 
  * The TYPO3 project - inspiring people to share!
  */
 
+use Psr\Http\Message\ServerRequestInterface;
 use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface;
 use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface;
+use TYPO3\CMS\Adminpanel\Service\ConfigurationService;
 use TYPO3\CMS\Adminpanel\Service\ModuleLoader;
 use TYPO3\CMS\Adminpanel\View\AdminPanelView;
 use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
 use TYPO3\CMS\Adminpanel\Service\ModuleLoader;
 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\Backend\Routing\UriBuilder;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Core\SingletonInterface;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+use TYPO3\CMS\Core\Utility\PathUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
 
 /**
  * Main controller for the admin panel
 
 /**
  * Main controller for the admin panel
@@ -35,80 +36,166 @@ use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 class MainController implements SingletonInterface
 {
     /**
 class MainController implements SingletonInterface
 {
     /**
-     * @var array<AdminPanelModuleInterface>
+     * @var AdminPanelModuleInterface[]
      */
     protected $modules = [];
 
      */
     protected $modules = [];
 
+    /**
+     * @var ModuleLoader
+     */
+    protected $moduleLoader;
+
+    /**
+     * @var UriBuilder
+     */
+    protected $uriBuilder;
+
+    /**
+     * @var ConfigurationService
+     */
+    protected $configurationService;
+
+    /**
+     * @var array
+     */
+    protected $adminPanelModuleConfiguration;
+
+    /**
+     * @param ModuleLoader $moduleLoader
+     * @param UriBuilder $uriBuilder
+     * @param ConfigurationService $configurationService
+     */
+    public function __construct(
+        ModuleLoader $moduleLoader = null,
+        UriBuilder $uriBuilder = null,
+        ConfigurationService $configurationService = null
+    ) {
+        $this->moduleLoader = $moduleLoader ?? GeneralUtility::makeInstance(ModuleLoader::class);
+        $this->uriBuilder = $uriBuilder ?? GeneralUtility::makeInstance(UriBuilder::class);
+        $this->configurationService = $configurationService ?? GeneralUtility::makeInstance(ConfigurationService::class);
+        $this->adminPanelModuleConfiguration = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? [];
+    }
+
     /**
      * Initializes settings for the admin panel.
      *
     /**
      * Initializes settings for the admin panel.
      *
-     * @param \TYPO3\CMS\Core\Http\ServerRequest $request
+     * @param ServerRequestInterface $request
      */
      */
-    public function initialize(ServerRequest $request): void
+    public function initialize(ServerRequestInterface $request): void
     {
     {
-        $moduleLoader = GeneralUtility::makeInstance(ModuleLoader::class);
-        $this->modules = $moduleLoader->getModulesFromConfiguration();
-        $this->saveConfiguration();
+        $this->modules = $this->moduleLoader->validateSortAndInitializeModules(
+            $this->adminPanelModuleConfiguration
+        );
+        $this->configurationService->saveConfiguration($this->modules, $request);
 
 
-        foreach ($this->modules as $module) {
-            if ($module->isEnabled()) {
-                $module->initializeModule($request);
+        if ($this->isAdminPanelActivated()) {
+            foreach ($this->modules as $module) {
+                if ($module->isEnabled()) {
+                    $subModules = $this->moduleLoader->validateSortAndInitializeSubModules(
+                        $this->adminPanelModuleConfiguration[$module->getIdentifier()]['submodules'] ?? []
+                    );
+                    foreach ($subModules as $subModule) {
+                        $subModule->initializeModule($request);
+                    }
+                    $module->setSubModules($subModules);
+                    $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
+     * Renders the admin panel
      *
      * @return string
      */
     public function render(): string
     {
      *
      * @return string
      */
     public function render(): string
     {
-        // handling via legacy functions
+        // legacy handling, deprecated, will be removed in TYPO3 v10.0.
         $adminPanelView = GeneralUtility::makeInstance(AdminPanelView::class);
         $adminPanelView = GeneralUtility::makeInstance(AdminPanelView::class);
-        $adminPanelView->setModules($this->modules);
-        return $adminPanelView->display();
+        $hookObjectContent = $adminPanelView->callDeprecatedHookObject();
+        // end legacy handling
+
+        $resources = $this->getResources();
+
+        $view = GeneralUtility::makeInstance(StandaloneView::class);
+        $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Main.html';
+        $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
+        $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
+        $view->setLayoutRootPaths(['EXT:adminpanel/Resources/Private/Layouts']);
+
+        $view->assignMultiple(
+            [
+                'toggleActiveUrl' => $this->generateBackendUrl('ajax_adminPanel_toggle'),
+                'resources' => $resources,
+                'adminPanelActive' => $this->isAdminPanelActivated(),
+            ]
+        );
+        if ($this->isAdminPanelActivated()) {
+            $moduleResources = $this->getAdditionalResourcesForModules($this->modules);
+            $view->assignMultiple(
+                [
+                    'modules' => $this->modules,
+                    'hookObjectContent' => $hookObjectContent,
+                    'saveUrl' => $this->generateBackendUrl('ajax_adminPanel_saveForm'),
+                    'moduleResources' => $moduleResources,
+                ]
+            );
+        }
+
+        return $view->render();
     }
 
     /**
     }
 
     /**
-     * Save admin panel configuration to backend user UC
+     * Generate a url to a backend route
+     *
+     * @param string $route
+     * @return string
      */
      */
-    protected function saveConfiguration(): void
+    protected function generateBackendUrl(string $route): string
     {
     {
-        $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']);
+        return (string)$this->uriBuilder->buildUriFromRoute($route);
+    }
 
 
-            foreach ($this->modules as $module) {
-                if ($module->isEnabled() && $module->isOpen()) {
-                    $module->onSubmit($input);
-                }
+    /**
+     * Get additional resources (css, js) from modules and merge it to
+     * one array - returns an array of full html tags
+     *
+     * @param AdminPanelModuleInterface[] $modules
+     * @return array
+     */
+    protected function getAdditionalResourcesForModules(array $modules): array
+    {
+        $result = [
+            'js' => '',
+            'css' => '',
+        ];
+        foreach ($modules as $module) {
+            foreach ($module->getJavaScriptFiles() as $file) {
+                $result['js'] .= $this->getJsTag($file);
+            }
+            foreach ($module->getCssFiles() as $file) {
+                $result['css'] .= $this->getCssTag($file);
             }
             }
-            // Saving
-            $beUser->writeUC();
-            // Flush fluid template cache
-            $cacheManager = new CacheManager();
-            $cacheManager->setCacheConfigurations($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']);
-            $cacheManager->getCache('fluid_template')->flush();
         }
         }
+        return $result;
     }
 
     /**
     }
 
     /**
-     * Returns LanguageService
+     * Returns a link tag with the admin panel stylesheet
+     * defined using TBE_STYLES
      *
      *
-     * @return LanguageService
+     * @return string
      */
      */
-    protected function getLanguageService(): LanguageService
+    protected function getAdminPanelStylesheet(): string
     {
     {
-        return $GLOBALS['LANG'];
+        $result = '';
+        if (!empty($GLOBALS['TBE_STYLES']['stylesheets']['admPanel'])) {
+            $stylesheet = GeneralUtility::locationHeaderUrl($GLOBALS['TBE_STYLES']['stylesheets']['admPanel']);
+            $result = '<link rel="stylesheet" type="text/css" href="' .
+                      htmlspecialchars($stylesheet, ENT_QUOTES | ENT_HTML5) . '" />';
+        }
+        return $result;
     }
 
     /**
     }
 
     /**
@@ -122,10 +209,62 @@ class MainController implements SingletonInterface
     }
 
     /**
     }
 
     /**
-     * @return TypoScriptFrontendController
+     * Get a css tag for file - with absolute web path resolving
+     *
+     * @param string $cssFileLocation
+     * @return string
+     */
+    protected function getCssTag(string $cssFileLocation): string
+    {
+        $css = '<link type="text/css" rel="stylesheet" href="' .
+               htmlspecialchars(
+                   PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($cssFileLocation)),
+                   ENT_QUOTES | ENT_HTML5
+               ) .
+               '" media="all" />';
+        return $css;
+    }
+
+    /**
+     * Get a script tag for JavaScript with absolute paths
+     *
+     * @param string $jsFileLocation
+     * @return string
+     */
+    protected function getJsTag(string $jsFileLocation): string
+    {
+        $js = '<script type="text/javascript" src="' .
+              htmlspecialchars(
+                  PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($jsFileLocation)),
+                  ENT_QUOTES | ENT_HTML5
+              ) .
+              '"></script>';
+        return $js;
+    }
+
+    /**
+     * Return a string with tags for main admin panel resources
+     *
+     * @return string
+     */
+    protected function getResources(): string
+    {
+        $jsFileLocation = 'EXT:adminpanel/Resources/Public/JavaScript/AdminPanel.js';
+        $js = $this->getJsTag($jsFileLocation);
+        $cssFileLocation = 'EXT:adminpanel/Resources/Public/Css/adminpanel.css';
+        $css = $this->getCssTag($cssFileLocation);
+
+        return $css . $this->getAdminPanelStylesheet() . $js;
+    }
+
+    /**
+     * Returns true if admin panel was activated
+     * (switched "on" via GUI)
+     *
+     * @return bool
      */
      */
-    protected function getTypoScriptFrontendController(): TypoScriptFrontendController
+    protected function isAdminPanelActivated(): bool
     {
     {
-        return $GLOBALS['TSFE'];
+        return (bool)($this->getBackendUser()->uc['AdminPanel']['display_top'] ?? false);
     }
 }
     }
 }