95accbeec2f015580975d99851b2669c44bfe8db
[Packages/TYPO3.CMS.git] / typo3 / sysext / adminpanel / Classes / Controller / MainController.php
1 <?php
2 declare(strict_types = 1);
3
4 namespace TYPO3\CMS\Adminpanel\Controller;
5
6 /*
7 * This file is part of the TYPO3 CMS project.
8 *
9 * It is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License, either version 2
11 * of the License, or any later version.
12 *
13 * For the full copyright and license information, please read the
14 * LICENSE.txt file that was distributed with this source code.
15 *
16 * The TYPO3 project - inspiring people to share!
17 */
18
19 use Psr\Http\Message\ServerRequestInterface;
20 use TYPO3\CMS\Adminpanel\Modules\AdminPanelModuleInterface;
21 use TYPO3\CMS\Adminpanel\Service\ConfigurationService;
22 use TYPO3\CMS\Adminpanel\Service\ModuleLoader;
23 use TYPO3\CMS\Adminpanel\View\AdminPanelView;
24 use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
25 use TYPO3\CMS\Backend\Routing\UriBuilder;
26 use TYPO3\CMS\Core\Localization\LanguageService;
27 use TYPO3\CMS\Core\SingletonInterface;
28 use TYPO3\CMS\Core\Utility\GeneralUtility;
29 use TYPO3\CMS\Core\Utility\PathUtility;
30 use TYPO3\CMS\Fluid\View\StandaloneView;
31 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
32
33 /**
34 * Main controller for the admin panel
35 *
36 * @internal
37 */
38 class MainController implements SingletonInterface
39 {
40 /**
41 * @var AdminPanelModuleInterface[]
42 */
43 protected $modules = [];
44
45 /**
46 * @var ModuleLoader
47 */
48 protected $moduleLoader;
49
50 /**
51 * @var UriBuilder
52 */
53 protected $uriBuilder;
54
55 /**
56 * @var ConfigurationService
57 */
58 protected $configurationService;
59
60 /**
61 * @var array
62 */
63 private $adminPanelModuleConfiguration;
64
65 /**
66 * @param ModuleLoader $moduleLoader
67 * @param UriBuilder $uriBuilder
68 * @param ConfigurationService $configurationService
69 */
70 public function __construct(
71 ModuleLoader $moduleLoader = null,
72 UriBuilder $uriBuilder = null,
73 ConfigurationService $configurationService = null
74 ) {
75 $this->moduleLoader = $moduleLoader ?? GeneralUtility::makeInstance(ModuleLoader::class);
76 $this->uriBuilder = $uriBuilder ?? GeneralUtility::makeInstance(UriBuilder::class);
77 $this->configurationService = $configurationService ?? GeneralUtility::makeInstance(ConfigurationService::class);
78 $this->adminPanelModuleConfiguration = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? [];
79 }
80
81 /**
82 * Initializes settings for the admin panel.
83 *
84 * @param ServerRequestInterface $request
85 */
86 public function initialize(ServerRequestInterface $request): void
87 {
88 $this->modules = $this->moduleLoader->validateSortAndInitializeModules(
89 $this->adminPanelModuleConfiguration
90 );
91 $this->configurationService->saveConfiguration($this->modules, $request);
92
93 if ($this->isAdminPanelActivated()) {
94 foreach ($this->modules as $module) {
95 if ($module->isEnabled()) {
96 $subModules = $this->moduleLoader->validateSortAndInitializeSubModules(
97 $this->adminPanelModuleConfiguration[$module->getIdentifier()]['submodules'] ?? []
98 );
99 foreach ($subModules as $subModule) {
100 $subModule->initializeModule($request);
101 }
102 $module->setSubModules($subModules);
103 $module->initializeModule($request);
104 }
105 }
106 }
107 }
108
109 /**
110 * Renders the admin panel
111 *
112 * @return string
113 */
114 public function render(): string
115 {
116 // legacy handling
117 $adminPanelView = GeneralUtility::makeInstance(AdminPanelView::class);
118 $hookObjectContent = $adminPanelView->callDeprecatedHookObject();
119 // end legacy handling
120
121 $resources = $this->getResources();
122
123 $view = GeneralUtility::makeInstance(StandaloneView::class);
124 $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Main.html';
125 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
126 $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
127 $view->setLayoutRootPaths(['EXT:adminpanel/Resources/Private/Layouts']);
128
129 $view->assignMultiple(
130 [
131 'toggleActiveUrl' => $this->generateBackendUrl('ajax_adminPanel_toggle'),
132 'resources' => $resources,
133 'adminPanelActive' => $this->isAdminPanelActivated(),
134 ]
135 );
136 if ($this->isAdminPanelActivated()) {
137 $moduleResources = $this->getAdditionalResourcesForModules($this->modules);
138 $view->assignMultiple(
139 [
140 'modules' => $this->modules,
141 'hookObjectContent' => $hookObjectContent,
142 'saveUrl' => $this->generateBackendUrl('ajax_adminPanel_saveForm'),
143 'moduleResources' => $moduleResources,
144 ]
145 );
146 }
147
148 return $view->render();
149 }
150
151 /**
152 * Generate a url to a backend route
153 *
154 * @param string $route
155 * @return string
156 */
157 protected function generateBackendUrl(string $route): string
158 {
159 return (string)$this->uriBuilder->buildUriFromRoute($route);
160 }
161
162 /**
163 * Get additional resources (css, js) from modules and merge it to
164 * one array - returns an array of full html tags
165 *
166 * @param AdminPanelModuleInterface[] $modules
167 * @return array
168 */
169 protected function getAdditionalResourcesForModules(array $modules): array
170 {
171 $result = [
172 'js' => '',
173 'css' => '',
174 ];
175 foreach ($modules as $module) {
176 foreach ($module->getJavaScriptFiles() as $file) {
177 $result['js'] .= $this->getJsTag($file);
178 }
179 foreach ($module->getCssFiles() as $file) {
180 $result['css'] .= $this->getCssTag($file);
181 }
182 }
183 return $result;
184 }
185
186 /**
187 * Returns a link tag with the admin panel stylesheet
188 * defined using TBE_STYLES
189 *
190 * @return string
191 */
192 protected function getAdminPanelStylesheet(): string
193 {
194 $result = '';
195 if (!empty($GLOBALS['TBE_STYLES']['stylesheets']['admPanel'])) {
196 $stylesheet = GeneralUtility::locationHeaderUrl($GLOBALS['TBE_STYLES']['stylesheets']['admPanel']);
197 $result = '<link rel="stylesheet" type="text/css" href="' .
198 htmlspecialchars($stylesheet, ENT_QUOTES | ENT_HTML5) . '" />';
199 }
200 return $result;
201 }
202
203 /**
204 * Returns the current BE user.
205 *
206 * @return FrontendBackendUserAuthentication
207 */
208 protected function getBackendUser(): FrontendBackendUserAuthentication
209 {
210 return $GLOBALS['BE_USER'];
211 }
212
213 /**
214 * Get a css tag for file - with absolute web path resolving
215 *
216 * @param string $cssFileLocation
217 * @return string
218 */
219 protected function getCssTag(string $cssFileLocation): string
220 {
221 $css = '<link type="text/css" rel="stylesheet" href="' .
222 htmlspecialchars(
223 PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($cssFileLocation)),
224 ENT_QUOTES | ENT_HTML5
225 ) .
226 '" media="all" />';
227 return $css;
228 }
229
230 /**
231 * Get a script tag for JavaScript with absolute paths
232 *
233 * @param string $jsFileLocation
234 * @return string
235 */
236 protected function getJsTag(string $jsFileLocation): string
237 {
238 $js = '<script type="text/javascript" src="' .
239 htmlspecialchars(
240 PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($jsFileLocation)),
241 ENT_QUOTES | ENT_HTML5
242 ) .
243 '"></script>';
244 return $js;
245 }
246
247 /**
248 * Returns LanguageService
249 *
250 * @return LanguageService
251 */
252 protected function getLanguageService(): LanguageService
253 {
254 return $GLOBALS['LANG'];
255 }
256
257 /**
258 * Return a string with tags for main admin panel resources
259 *
260 * @return string
261 */
262 protected function getResources(): string
263 {
264 $jsFileLocation = 'EXT:adminpanel/Resources/Public/JavaScript/AdminPanel.js';
265 $js = $this->getJsTag($jsFileLocation);
266 $cssFileLocation = 'EXT:adminpanel/Resources/Public/Css/adminpanel.css';
267 $css = $this->getCssTag($cssFileLocation);
268
269 return $css . $this->getAdminPanelStylesheet() . $js;
270 }
271
272 /**
273 * @return TypoScriptFrontendController
274 */
275 protected function getTypoScriptFrontendController(): TypoScriptFrontendController
276 {
277 return $GLOBALS['TSFE'];
278 }
279
280 /**
281 * Returns true if admin panel was activated
282 * (switched "on" via GUI)
283 *
284 * @return bool
285 */
286 protected function isAdminPanelActivated(): bool
287 {
288 return (bool)($this->getBackendUser()->uc['TSFE_adminConfig']['display_top'] ?? false);
289 }
290 }