[!!!][FEATURE] Introduce Backend Routing
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / BackendModuleRequestHandler.php
1 <?php
2 namespace TYPO3\CMS\Backend;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
18 use TYPO3\CMS\Core\Core\Bootstrap;
19 use TYPO3\CMS\Core\FormProtection\FormProtectionFactory;
20 use TYPO3\CMS\Core\Exception;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Extbase\Object\ObjectManager;
23
24 /**
25 * Handles the request for backend modules and wizards
26 */
27 class BackendModuleRequestHandler implements \TYPO3\CMS\Core\Core\RequestHandlerInterface {
28
29 /**
30 * @var Bootstrap
31 */
32 protected $bootstrap;
33
34 /**
35 * @var array
36 */
37 protected $moduleRegistry = array();
38
39 /**
40 * @var BackendUserAuthentication
41 */
42 protected $backendUserAuthentication;
43
44 /**
45 * @param Bootstrap $bootstrap The TYPO3 core bootstrap
46 */
47 public function __construct(Bootstrap $bootstrap) {
48 $this->bootstrap = $bootstrap;
49 }
50
51 /**
52 * Handles the request, evaluating the configuration and executes the module accordingly
53 *
54 * @throws Exception
55 */
56 public function handleRequest() {
57 $this->boot();
58
59 $this->moduleRegistry = $GLOBALS['TBE_MODULES'];
60
61 if (!$this->isValidModuleRequest()) {
62 throw new Exception('The CSRF protection token for the requested module is missing or invalid', 1417988921);
63 }
64
65 // Set to empty as it is not needed / always coming from typo3/mod.php
66 $GLOBALS['BACK_PATH'] = '';
67
68 $this->backendUserAuthentication = $GLOBALS['BE_USER'];
69
70 $moduleName = (string)GeneralUtility::_GET('M');
71 if ($this->isDispatchedModule($moduleName)) {
72 $isDispatched = $this->dispatchModule($moduleName);
73 } else {
74 $isDispatched = $this->callTraditionalModule($moduleName);
75 }
76 if ($isDispatched === FALSE) {
77 throw new Exception('No module "' . $moduleName . '" could be found.', 1294585070);
78 }
79 }
80
81 /**
82 * Execute TYPO3 bootstrap
83 */
84 protected function boot() {
85 $this->bootstrap->checkLockedBackendAndRedirectOrDie()
86 ->checkBackendIpOrDie()
87 ->checkSslBackendAndRedirectIfNeeded()
88 ->checkValidBrowserOrDie()
89 ->initializeBackendRouter()
90 ->loadExtensionTables(TRUE)
91 ->initializeSpriteManager()
92 ->initializeBackendUser()
93 ->initializeBackendAuthentication()
94 ->initializeLanguageObject()
95 ->initializeBackendTemplate()
96 ->endOutputBufferingAndCleanPreviousOutput()
97 ->initializeOutputCompression()
98 ->sendHttpHeaders();
99 }
100
101 /**
102 * This request handler can handle any backend request coming from mod.php
103 *
104 * @return bool
105 */
106 public function canHandleRequest() {
107 return (TYPO3_REQUESTTYPE & TYPO3_REQUESTTYPE_BE) && !empty((string)GeneralUtility::_GET('M'));
108 }
109
110 /**
111 * Checks if all parameters are met.
112 *
113 * @return bool
114 */
115 protected function isValidModuleRequest() {
116 return $this->getFormProtection()->validateToken((string)GeneralUtility::_GP('moduleToken'), 'moduleCall', (string)GeneralUtility::_GET('M'));
117 }
118
119 /**
120 * A dispatched module, currently only Extbase modules are dispatched,
121 * traditional modules have a module path set.
122 *
123 * @param string $moduleName
124 * @return bool
125 */
126 protected function isDispatchedModule($moduleName) {
127 return empty($this->moduleRegistry['_PATHS'][$moduleName]);
128 }
129
130 /**
131 * Executes the module dispatcher which calls the module appropriately.
132 * Currently only used by Extbase
133 *
134 * @param string $moduleName
135 * @return bool
136 */
137 protected function dispatchModule($moduleName) {
138 if (is_array($this->moduleRegistry['_dispatcher'])) {
139 foreach ($this->moduleRegistry['_dispatcher'] as $dispatcherClassName) {
140 $dispatcher = GeneralUtility::makeInstance(ObjectManager::class)->get($dispatcherClassName);
141 if ($dispatcher->callModule($moduleName) === TRUE) {
142 return TRUE;
143 break;
144 }
145 }
146 }
147 return FALSE;
148 }
149
150 /**
151 * Calls traditional modules which are identified by having a index.php in their directory
152 * and were previously located within the global scope.
153 *
154 * @param string $moduleName
155 * @return bool
156 */
157 protected function callTraditionalModule($moduleName) {
158 $moduleBasePath = $this->moduleRegistry['_PATHS'][$moduleName];
159 $GLOBALS['MCONF'] = $moduleConfiguration = $this->getModuleConfiguration($moduleName);
160 if (!empty($moduleConfiguration['access'])) {
161 $this->backendUserAuthentication->modAccess($moduleConfiguration, TRUE);
162 }
163 if (file_exists($moduleBasePath . 'index.php')) {
164 global $SOBE;
165 require $moduleBasePath . 'index.php';
166 return TRUE;
167 }
168 return FALSE;
169 }
170
171 /**
172 * Returns the module configuration which is either provided in a conf.php file
173 * or during module registration
174 *
175 * @param string $moduleName
176 * @return array
177 */
178 protected function getModuleConfiguration($moduleName) {
179 $moduleBasePath = $this->moduleRegistry['_PATHS'][$moduleName];
180 if (file_exists($moduleBasePath . 'conf.php')) {
181 // Some modules still rely on this global configuration array in a conf.php file
182 require $moduleBasePath . 'conf.php';
183 $moduleConfiguration = $MCONF;
184 } else {
185 $moduleConfiguration = $this->moduleRegistry['_configuration'][$moduleName];
186 }
187 return $moduleConfiguration;
188 }
189
190
191 /**
192 * Returns the priority - how eager the handler is to actually handle the request.
193 *
194 * @return int The priority of the request handler.
195 */
196 public function getPriority() {
197 return 90;
198 }
199
200 /**
201 * Wrapper method for static form protection utility
202 *
203 * @return \TYPO3\CMS\Core\FormProtection\AbstractFormProtection
204 */
205 protected function getFormProtection() {
206 return FormProtectionFactory::get();
207 }
208
209 }