[TASK] Migrate tce_db, tce_file and FormEngine entry points to routing
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / SimpleDataHandlerController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller;
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 Psr\Http\Message\ServerRequestInterface;
18 use TYPO3\CMS\Core\Http\Response;
19 use TYPO3\CMS\Core\Messaging\AbstractMessage;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21 use TYPO3\CMS\Core\DataHandling\DataHandler;
22 use TYPO3\CMS\Core\Utility\MathUtility;
23 use TYPO3\CMS\Backend\Clipboard\Clipboard;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
25 use TYPO3\CMS\Core\Utility\HttpUtility;
26 use TYPO3\CMS\Core\Http\AjaxRequestHandler;
27 use TYPO3\CMS\Core\Messaging\FlashMessageService;
28
29 /**
30 * Script Class, creating object of \TYPO3\CMS\Core\DataHandling\DataHandler and
31 * sending the posted data to the object.
32 *
33 * Used by many smaller forms/links in TYPO3, including the QuickEdit module.
34 * Is not used by FormEngine though (main form rendering script) - that uses the same class (TCEmain) but makes its own initialization (to save the redirect request).
35 * For all other cases than FormEngine it is recommended to use this script for submitting your editing forms - but the best solution in any case would probably be to link your application to FormEngine, that will give you easy form-rendering as well.
36 */
37 class SimpleDataHandlerController implements \TYPO3\CMS\Core\Http\ControllerInterface {
38
39 /**
40 * Array. Accepts options to be set in TCE object. Currently it supports "reverseOrder" (bool).
41 *
42 * @var array
43 */
44 public $flags;
45
46 /**
47 * Data array on the form [tablename][uid][fieldname] = value
48 *
49 * @var array
50 */
51 public $data;
52
53 /**
54 * Command array on the form [tablename][uid][command] = value.
55 * This array may get additional data set internally based on clipboard commands send in CB var!
56 *
57 * @var array
58 */
59 public $cmd;
60
61 /**
62 * Array passed to ->setMirror.
63 *
64 * @var array
65 */
66 public $mirror;
67
68 /**
69 * Cache command sent to ->clear_cacheCmd
70 *
71 * @var string
72 */
73 public $cacheCmd;
74
75 /**
76 * Redirect URL. Script will redirect to this location after performing operations (unless errors has occurred)
77 *
78 * @var string
79 */
80 public $redirect;
81
82 /**
83 * Boolean. If set, errors will be printed on screen instead of redirection. Should always be used, otherwise you will see no errors if they happen.
84 *
85 * @var int
86 */
87 public $prErr;
88
89 /**
90 * Clipboard command array. May trigger changes in "cmd"
91 *
92 * @var array
93 */
94 public $CB;
95
96 /**
97 * Verification code
98 *
99 * @var string
100 */
101 public $vC;
102
103 /**
104 * Boolean. Update Page Tree Trigger. If set and the manipulated records are pages then the update page tree signal will be set.
105 *
106 * @var int
107 */
108 public $uPT;
109
110 /**
111 * TYPO3 Core Engine
112 *
113 * @var \TYPO3\CMS\Core\DataHandling\DataHandler
114 */
115 public $tce;
116
117 /**
118 * Constructor
119 */
120 public function __construct() {
121 $GLOBALS['SOBE'] = $this;
122 $this->init();
123 }
124
125 /**
126 * Initialization of the class
127 *
128 * @return void
129 */
130 public function init() {
131 $beUser = $this->getBackendUser();
132 // GPvars:
133 $this->flags = GeneralUtility::_GP('flags');
134 $this->data = GeneralUtility::_GP('data');
135 $this->cmd = GeneralUtility::_GP('cmd');
136 $this->mirror = GeneralUtility::_GP('mirror');
137 $this->cacheCmd = GeneralUtility::_GP('cacheCmd');
138 $this->redirect = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('redirect'));
139 $this->prErr = GeneralUtility::_GP('prErr');
140 $this->CB = GeneralUtility::_GP('CB');
141 $this->vC = GeneralUtility::_GP('vC');
142 $this->uPT = GeneralUtility::_GP('uPT');
143 // Creating TCEmain object
144 $this->tce = GeneralUtility::makeInstance(DataHandler::class);
145 $this->tce->stripslashes_values = 0;
146 // Configuring based on user prefs.
147 if ($beUser->uc['recursiveDelete']) {
148 // TRUE if the delete Recursive flag is set.
149 $this->tce->deleteTree = 1;
150 }
151 if ($beUser->uc['copyLevels']) {
152 // Set to number of page-levels to copy.
153 $this->tce->copyTree = MathUtility::forceIntegerInRange($beUser->uc['copyLevels'], 0, 100);
154 }
155 if ($beUser->uc['neverHideAtCopy']) {
156 $this->tce->neverHideAtCopy = 1;
157 }
158 $TCAdefaultOverride = $beUser->getTSConfigProp('TCAdefaults');
159 if (is_array($TCAdefaultOverride)) {
160 $this->tce->setDefaultsFromUserTS($TCAdefaultOverride);
161 }
162 // Reverse order.
163 if ($this->flags['reverseOrder']) {
164 $this->tce->reverseOrder = 1;
165 }
166 }
167
168 /**
169 * Clipboard pasting and deleting.
170 *
171 * @return void
172 */
173 public function initClipboard() {
174 if (is_array($this->CB)) {
175 $clipObj = GeneralUtility::makeInstance(Clipboard::class);
176 $clipObj->initializeClipboard();
177 if ($this->CB['paste']) {
178 $clipObj->setCurrentPad($this->CB['pad']);
179 $this->cmd = $clipObj->makePasteCmdArray(
180 $this->CB['paste'],
181 $this->cmd,
182 isset($this->CB['update']) ? $this->CB['update'] : NULL
183 );
184 }
185 if ($this->CB['delete']) {
186 $clipObj->setCurrentPad($this->CB['pad']);
187 $this->cmd = $clipObj->makeDeleteCmdArray($this->cmd);
188 }
189 }
190 }
191
192 /**
193 * Executing the posted actions ...
194 *
195 * @return void
196 */
197 public function main() {
198 // LOAD TCEmain with data and cmd arrays:
199 $this->tce->start($this->data, $this->cmd);
200 if (is_array($this->mirror)) {
201 $this->tce->setMirror($this->mirror);
202 }
203 // Checking referer / executing
204 $refInfo = parse_url(GeneralUtility::getIndpEnv('HTTP_REFERER'));
205 $httpHost = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY');
206 if ($httpHost != $refInfo['host'] && $this->vC != $this->getBackendUser()->veriCode() && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['doNotCheckReferer']) {
207 $this->tce->log('', 0, 0, 0, 1, 'Referer host "%s" and server host "%s" did not match and veriCode was not valid either!', 1, array($refInfo['host'], $httpHost));
208 } else {
209 // Register uploaded files
210 $this->tce->process_uploads($_FILES);
211 // Execute actions:
212 $this->tce->process_datamap();
213 $this->tce->process_cmdmap();
214 // Clearing cache:
215 if (!empty($this->cacheCmd)) {
216 $this->tce->clear_cacheCmd($this->cacheCmd);
217 }
218 // Update page tree?
219 if ($this->uPT && (isset($this->data['pages']) || isset($this->cmd['pages']))) {
220 BackendUtility::setUpdateSignal('updatePageTree');
221 }
222 }
223 }
224
225 /**
226 * Redirecting the user after the processing has been done.
227 * Might also display error messages directly, if any.
228 *
229 * @return void
230 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8
231 */
232 public function finish() {
233 GeneralUtility::logDeprecatedFunction();
234 // Prints errors, if...
235 if ($this->prErr) {
236 $this->tce->printLogErrorMessages($this->redirect);
237 }
238 if ($this->redirect) {
239 HttpUtility::redirect($this->redirect);
240 }
241 }
242
243 /**
244 * Injects the request object for the current request or subrequest
245 * As this controller goes only through the main() method, it just redirects to the given URL afterwards.
246 *
247 * @param ServerRequestInterface $request
248 * @return \Psr\Http\Message\ResponseInterface $response
249 */
250 public function processRequest(ServerRequestInterface $request) {
251 $formProtection = \TYPO3\CMS\Core\FormProtection\FormProtectionFactory::get();
252 $formToken = isset($request->getQueryParams()['formToken']) ? $request->getQueryParams()['formToken'] : $request->getParsedBody()['formToken'];
253 if ($formProtection->validateToken($formToken, 'tceAction')) {
254 $this->initClipboard();
255 $this->main();
256 }
257
258 // Write errors to flash message queue
259 if ($this->prErr) {
260 $this->tce->printLogErrorMessages($this->redirect);
261 }
262 /** @var Response $response */
263 $response = GeneralUtility::makeInstance(Response::class);
264 if ($this->redirect) {
265 $response = $response->withHeader('Location', GeneralUtility::locationHeaderUrl($this->redirect));
266 return $response->withStatus(303);
267 } else {
268 // empty response
269 return $response;
270 }
271 }
272
273 /**
274 * Processes all AJAX calls and returns a JSON formatted string
275 *
276 * @param array $parameters
277 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxRequestHandler
278 */
279 public function processAjaxRequest($parameters, AjaxRequestHandler $ajaxRequestHandler) {
280 // do the regular / main logic
281 $this->initClipboard();
282 $this->main();
283
284 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */
285 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
286
287 $content = array(
288 'redirect' => $this->redirect,
289 'messages' => array(),
290 'hasErrors' => FALSE
291 );
292
293 // Prints errors (= write them to the message queue)
294 if ($this->prErr) {
295 $content['hasErrors'] = TRUE;
296 $this->tce->printLogErrorMessages($this->redirect);
297 }
298
299 $messages = $flashMessageService->getMessageQueueByIdentifier()->getAllMessagesAndFlush();
300 if (!empty($messages)) {
301 foreach ($messages as $message) {
302 $content['messages'][] = array(
303 'title' => $message->getTitle(),
304 'message' => $message->getMessage(),
305 'severity' => $message->getSeverity()
306 );
307 if ($message->getSeverity() === AbstractMessage::ERROR) {
308 $content['hasErrors'] = TRUE;
309 }
310 }
311 }
312 $ajaxRequestHandler->setContentFormat('json');
313 $ajaxRequestHandler->setContent($content);
314 }
315
316 /**
317 * Returns the current BE user.
318 *
319 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
320 */
321 protected function getBackendUser() {
322 return $GLOBALS['BE_USER'];
323 }
324
325 }