[FEATURE] Add HTTPS security check to reports module
[Packages/TYPO3.CMS.git] / typo3 / sysext / reports / Classes / Controller / ReportController.php
1 <?php
2 declare(strict_types = 1);
3 namespace TYPO3\CMS\Reports\Controller;
4
5 /*
6 * This file is part of the TYPO3 CMS project.
7 *
8 * It is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License, either version 2
10 * of the License, or any later version.
11 *
12 * For the full copyright and license information, please read the
13 * LICENSE.txt file that was distributed with this source code.
14 *
15 * The TYPO3 project - inspiring people to share!
16 */
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Routing\UriBuilder;
20 use TYPO3\CMS\Backend\Template\ModuleTemplate;
21 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
22 use TYPO3\CMS\Core\Http\HtmlResponse;
23 use TYPO3\CMS\Core\Http\RedirectResponse;
24 use TYPO3\CMS\Core\Localization\LanguageService;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Fluid\View\StandaloneView;
27 use TYPO3\CMS\Reports\ReportInterface;
28 use TYPO3\CMS\Reports\RequestAwareReportInterface;
29 use TYPO3Fluid\Fluid\View\ViewInterface;
30
31 /**
32 * Reports controller
33 */
34 class ReportController
35 {
36 /**
37 * ModuleTemplate object
38 *
39 * @var ModuleTemplate
40 */
41 protected $moduleTemplate;
42
43 /**
44 * @var ViewInterface
45 */
46 protected $view;
47
48 /**
49 * Module name for the shortcut
50 *
51 * @var string
52 */
53 protected $shortcutName;
54
55 /**
56 * Instantiate the report controller
57 */
58 public function __construct()
59 {
60 $this->moduleTemplate = GeneralUtility::makeInstance(ModuleTemplate::class);
61 }
62
63 /**
64 * Injects the request object for the current request, and renders correct action
65 *
66 * @param ServerRequestInterface $request the current request
67 * @return ResponseInterface the response with the content
68 */
69 public function handleRequest(ServerRequestInterface $request): ResponseInterface
70 {
71 $actionDefault = $request->getQueryParams()['action'] ?? $request->getParsedBody()['action'];
72 $action = $actionDefault ?: 'index';
73 $extension = $request->getQueryParams()['extension'] ?? $request->getParsedBody()['extension'];
74 $isRedirect = $request->getQueryParams()['redirect'] ?? $request->getParsedBody()['redirect'] ?? false;
75
76 if ($actionDefault !== 'index' && !$isRedirect && !$extension
77 && is_array($GLOBALS['BE_USER']->uc['reports']['selection'])) {
78 $previousSelection = $GLOBALS['BE_USER']->uc['reports']['selection'];
79 if (!empty($previousSelection['extension']) && !empty($previousSelection['report'])) {
80 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
81 return new RedirectResponse((string)$uriBuilder->buildUriFromRoute('system_reports', [
82 'action' => 'detail',
83 'extension' => $previousSelection['extension'],
84 'report' => $previousSelection['report'],
85 'redirect' => 1,
86 ]), 303);
87 }
88 }
89
90 $this->initializeView($action);
91
92 $result = call_user_func_array([$this, $action . 'Action'], [$request]);
93 if ($result instanceof ResponseInterface) {
94 return $result;
95 }
96
97 $this->generateMenu($request);
98 $this->generateButtons();
99
100 $this->moduleTemplate->setContent($this->view->render());
101 return new HtmlResponse($this->moduleTemplate->renderContent());
102 }
103
104 /**
105 * @param string $templateName
106 */
107 protected function initializeView(string $templateName)
108 {
109 $this->view = GeneralUtility::makeInstance(StandaloneView::class);
110 $this->view->setTemplate($templateName);
111 $this->view->setTemplateRootPaths(['EXT:reports/Resources/Private/Templates/Report']);
112 $this->view->setPartialRootPaths(['EXT:reports/Resources/Private/Partials']);
113 $this->view->setLayoutRootPaths(['EXT:reports/Resources/Private/Layouts']);
114 $this->view->getRequest()->setControllerExtensionName('Reports');
115 }
116
117 /**
118 * Overview
119 */
120 public function indexAction()
121 {
122 $this->view->assign('reports', $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports']);
123 $this->saveState();
124 }
125
126 /**
127 * Display a single report
128 *
129 * @param ServerRequestInterface $request
130 */
131 public function detailAction(ServerRequestInterface $request)
132 {
133 $content = $error = '';
134 $extension = $request->getQueryParams()['extension'] ?? $request->getParsedBody()['extension'];
135 $report = $request->getQueryParams()['report'] ?? $request->getParsedBody()['report'];
136
137 $reportClass = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports'][$extension][$report]['report'] ?? null;
138
139 $reportInstance = GeneralUtility::makeInstance($reportClass, $this);
140
141 if ($reportInstance instanceof ReportInterface) {
142 if ($reportInstance instanceof RequestAwareReportInterface) {
143 $content = $reportInstance->getReport($request);
144 } else {
145 $content = $reportInstance->getReport();
146 }
147 $this->saveState($extension, $report);
148 } else {
149 $error = $reportClass . ' does not implement the Report Interface which is necessary to be displayed here.';
150 }
151
152 $this->view->assignMultiple([
153 'content' => $content,
154 'error' => $error,
155 'report' => $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports'][$extension][$report],
156 ]);
157 }
158
159 /**
160 * Generates the menu
161 *
162 * @param ServerRequestInterface $request
163 */
164 protected function generateMenu(ServerRequestInterface $request)
165 {
166 $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
167 $lang = $this->getLanguageService();
168 $lang->includeLLFile('EXT:reports/Resources/Private/Language/locallang.xlf');
169 $menu = $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->makeMenu();
170 $menu->setIdentifier('WebFuncJumpMenu');
171 $menuItem = $menu
172 ->makeMenuItem()
173 ->setHref(
174 $uriBuilder->buildUriFromRoute('system_reports', ['action' => 'index'])
175 )
176 ->setTitle($lang->getLL('reports_overview'));
177 $menu->addMenuItem($menuItem);
178 $this->shortcutName = $lang->getLL('reports_overview');
179
180 $extensionParam = $request->getQueryParams()['extension'] ?? $request->getParsedBody()['extension'];
181 $reportParam = $request->getQueryParams()['report'] ?? $request->getParsedBody()['report'];
182
183 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['reports'] as $extKey => $reports) {
184 foreach ($reports as $reportName => $report) {
185 $menuItem = $menu
186 ->makeMenuItem()
187 ->setHref($uriBuilder->buildUriFromRoute(
188 'system_reports',
189 ['action' => 'detail', 'extension' => $extKey, 'report' => $reportName]
190 ))
191 ->setTitle($this->getLanguageService()->sL($report['title']));
192 if ($extensionParam === $extKey && $reportParam === $reportName) {
193 $menuItem->setActive(true);
194 $this->shortcutName = $menuItem->getTitle();
195 }
196 $menu->addMenuItem($menuItem);
197 }
198 }
199 $this->moduleTemplate->getDocHeaderComponent()->getMenuRegistry()->addMenu($menu);
200 }
201
202 /**
203 * Gets all buttons for the docHeader
204 */
205 protected function generateButtons()
206 {
207 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
208
209 $shortcutButton = $buttonBar->makeShortcutButton()
210 ->setModuleName('system_reports')
211 ->setGetVariables(['action', 'extension', 'report'])
212 ->setDisplayName($this->shortcutName);
213 $buttonBar->addButton($shortcutButton);
214 }
215
216 /**
217 * Save the selected report
218 *
219 * @param string $extension Extension name
220 * @param string $report Report name
221 */
222 protected function saveState(string $extension = '', string $report = '')
223 {
224 $this->getBackendUser()->uc['reports']['selection'] = [
225 'extension' => $extension,
226 'report' => $report,
227 ];
228 $this->getBackendUser()->writeUC();
229 }
230
231 /**
232 * @return BackendUserAuthentication
233 */
234 protected function getBackendUser(): BackendUserAuthentication
235 {
236 return $GLOBALS['BE_USER'];
237 }
238
239 /**
240 * @return LanguageService
241 */
242 protected function getLanguageService(): LanguageService
243 {
244 return $GLOBALS['LANG'];
245 }
246 }