b3479015af90e27c5e99d2f01885368b4c9d2874
[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\SingletonInterface;
27 use TYPO3\CMS\Core\Utility\GeneralUtility;
28 use TYPO3\CMS\Core\Utility\PathUtility;
29 use TYPO3\CMS\Fluid\View\StandaloneView;
30
31 /**
32 * Main controller for the admin panel
33 *
34 * @internal
35 */
36 class MainController implements SingletonInterface
37 {
38 /**
39 * @var AdminPanelModuleInterface[]
40 */
41 protected $modules = [];
42
43 /**
44 * @var ModuleLoader
45 */
46 protected $moduleLoader;
47
48 /**
49 * @var UriBuilder
50 */
51 protected $uriBuilder;
52
53 /**
54 * @var ConfigurationService
55 */
56 protected $configurationService;
57
58 /**
59 * @var array
60 */
61 protected $adminPanelModuleConfiguration;
62
63 /**
64 * @param ModuleLoader $moduleLoader
65 * @param UriBuilder $uriBuilder
66 * @param ConfigurationService $configurationService
67 */
68 public function __construct(
69 ModuleLoader $moduleLoader = null,
70 UriBuilder $uriBuilder = null,
71 ConfigurationService $configurationService = null
72 ) {
73 $this->moduleLoader = $moduleLoader ?? GeneralUtility::makeInstance(ModuleLoader::class);
74 $this->uriBuilder = $uriBuilder ?? GeneralUtility::makeInstance(UriBuilder::class);
75 $this->configurationService = $configurationService ?? GeneralUtility::makeInstance(ConfigurationService::class);
76 $this->adminPanelModuleConfiguration = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules'] ?? [];
77 }
78
79 /**
80 * Initializes settings for the admin panel.
81 *
82 * @param ServerRequestInterface $request
83 */
84 public function initialize(ServerRequestInterface $request): void
85 {
86 $this->modules = $this->moduleLoader->validateSortAndInitializeModules(
87 $this->adminPanelModuleConfiguration
88 );
89 $this->configurationService->saveConfiguration($this->modules, $request);
90
91 if ($this->isAdminPanelActivated()) {
92 foreach ($this->modules as $module) {
93 if ($module->isEnabled()) {
94 $subModules = $this->moduleLoader->validateSortAndInitializeSubModules(
95 $this->adminPanelModuleConfiguration[$module->getIdentifier()]['submodules'] ?? []
96 );
97 foreach ($subModules as $subModule) {
98 $subModule->initializeModule($request);
99 }
100 $module->setSubModules($subModules);
101 $module->initializeModule($request);
102 }
103 }
104 }
105 }
106
107 /**
108 * Renders the admin panel
109 *
110 * @return string
111 */
112 public function render(): string
113 {
114 // legacy handling, deprecated, will be removed in TYPO3 v10.0.
115 $adminPanelView = GeneralUtility::makeInstance(AdminPanelView::class);
116 $hookObjectContent = $adminPanelView->callDeprecatedHookObject();
117 // end legacy handling
118
119 $resources = $this->getResources();
120
121 $view = GeneralUtility::makeInstance(StandaloneView::class);
122 $templateNameAndPath = 'EXT:adminpanel/Resources/Private/Templates/Main.html';
123 $view->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templateNameAndPath));
124 $view->setPartialRootPaths(['EXT:adminpanel/Resources/Private/Partials']);
125 $view->setLayoutRootPaths(['EXT:adminpanel/Resources/Private/Layouts']);
126
127 $view->assignMultiple(
128 [
129 'toggleActiveUrl' => $this->generateBackendUrl('ajax_adminPanel_toggle'),
130 'resources' => $resources,
131 'adminPanelActive' => $this->isAdminPanelActivated(),
132 ]
133 );
134 if ($this->isAdminPanelActivated()) {
135 $moduleResources = $this->getAdditionalResourcesForModules($this->modules);
136 $view->assignMultiple(
137 [
138 'modules' => $this->modules,
139 'hookObjectContent' => $hookObjectContent,
140 'saveUrl' => $this->generateBackendUrl('ajax_adminPanel_saveForm'),
141 'moduleResources' => $moduleResources,
142 ]
143 );
144 }
145
146 return $view->render();
147 }
148
149 /**
150 * Generate a url to a backend route
151 *
152 * @param string $route
153 * @return string
154 */
155 protected function generateBackendUrl(string $route): string
156 {
157 return (string)$this->uriBuilder->buildUriFromRoute($route);
158 }
159
160 /**
161 * Get additional resources (css, js) from modules and merge it to
162 * one array - returns an array of full html tags
163 *
164 * @param AdminPanelModuleInterface[] $modules
165 * @return array
166 */
167 protected function getAdditionalResourcesForModules(array $modules): array
168 {
169 $result = [
170 'js' => '',
171 'css' => '',
172 ];
173 foreach ($modules as $module) {
174 foreach ($module->getJavaScriptFiles() as $file) {
175 $result['js'] .= $this->getJsTag($file);
176 }
177 foreach ($module->getCssFiles() as $file) {
178 $result['css'] .= $this->getCssTag($file);
179 }
180 }
181 return $result;
182 }
183
184 /**
185 * Returns a link tag with the admin panel stylesheet
186 * defined using TBE_STYLES
187 *
188 * @return string
189 */
190 protected function getAdminPanelStylesheet(): string
191 {
192 $result = '';
193 if (!empty($GLOBALS['TBE_STYLES']['stylesheets']['admPanel'])) {
194 $stylesheet = GeneralUtility::locationHeaderUrl($GLOBALS['TBE_STYLES']['stylesheets']['admPanel']);
195 $result = '<link rel="stylesheet" type="text/css" href="' .
196 htmlspecialchars($stylesheet, ENT_QUOTES | ENT_HTML5) . '" />';
197 }
198 return $result;
199 }
200
201 /**
202 * Returns the current BE user.
203 *
204 * @return FrontendBackendUserAuthentication
205 */
206 protected function getBackendUser(): FrontendBackendUserAuthentication
207 {
208 return $GLOBALS['BE_USER'];
209 }
210
211 /**
212 * Get a css tag for file - with absolute web path resolving
213 *
214 * @param string $cssFileLocation
215 * @return string
216 */
217 protected function getCssTag(string $cssFileLocation): string
218 {
219 $css = '<link type="text/css" rel="stylesheet" href="' .
220 htmlspecialchars(
221 PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($cssFileLocation)),
222 ENT_QUOTES | ENT_HTML5
223 ) .
224 '" media="all" />';
225 return $css;
226 }
227
228 /**
229 * Get a script tag for JavaScript with absolute paths
230 *
231 * @param string $jsFileLocation
232 * @return string
233 */
234 protected function getJsTag(string $jsFileLocation): string
235 {
236 $js = '<script type="text/javascript" src="' .
237 htmlspecialchars(
238 PathUtility::getAbsoluteWebPath(GeneralUtility::getFileAbsFileName($jsFileLocation)),
239 ENT_QUOTES | ENT_HTML5
240 ) .
241 '"></script>';
242 return $js;
243 }
244
245 /**
246 * Return a string with tags for main admin panel resources
247 *
248 * @return string
249 */
250 protected function getResources(): string
251 {
252 $jsFileLocation = 'EXT:adminpanel/Resources/Public/JavaScript/AdminPanel.js';
253 $js = $this->getJsTag($jsFileLocation);
254 $cssFileLocation = 'EXT:adminpanel/Resources/Public/Css/adminpanel.css';
255 $css = $this->getCssTag($cssFileLocation);
256
257 return $css . $this->getAdminPanelStylesheet() . $js;
258 }
259
260 /**
261 * Returns true if admin panel was activated
262 * (switched "on" via GUI)
263 *
264 * @return bool
265 */
266 protected function isAdminPanelActivated(): bool
267 {
268 return (bool)($this->getBackendUser()->uc['AdminPanel']['display_top'] ?? false);
269 }
270 }