d222d9ec564ce6a8b21c406c7f743b963aeaa11b
[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\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Clipboard\Clipboard;
20 use TYPO3\CMS\Backend\Utility\BackendUtility;
21 use TYPO3\CMS\Core\DataHandling\DataHandler;
22 use TYPO3\CMS\Core\Http\JsonResponse;
23 use TYPO3\CMS\Core\Messaging\AbstractMessage;
24 use TYPO3\CMS\Core\Messaging\FlashMessageService;
25 use TYPO3\CMS\Core\Utility\GeneralUtility;
26 use TYPO3\CMS\Core\Utility\MathUtility;
27
28 /**
29 * Script Class, creating object of \TYPO3\CMS\Core\DataHandling\DataHandler and
30 * sending the posted data to the object.
31 *
32 * Used by many smaller forms/links in TYPO3, including the QuickEdit module.
33 * Is not used by FormEngine though (main form rendering script) - that uses the same class (DataHandler) but makes its own initialization (to save the redirect request).
34 * 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.
35 */
36 class SimpleDataHandlerController
37 {
38 /**
39 * Array. Accepts options to be set in TCE object. Currently it supports "reverseOrder" (bool).
40 *
41 * @var array
42 */
43 public $flags;
44
45 /**
46 * Data array on the form [tablename][uid][fieldname] = value
47 *
48 * @var array
49 */
50 public $data;
51
52 /**
53 * Command array on the form [tablename][uid][command] = value.
54 * This array may get additional data set internally based on clipboard commands send in CB var!
55 *
56 * @var array
57 */
58 public $cmd;
59
60 /**
61 * Array passed to ->setMirror.
62 *
63 * @var array
64 */
65 public $mirror;
66
67 /**
68 * Cache command sent to ->clear_cacheCmd
69 *
70 * @var string
71 */
72 public $cacheCmd;
73
74 /**
75 * Redirect URL. Script will redirect to this location after performing operations (unless errors has occurred)
76 *
77 * @var string
78 */
79 public $redirect;
80
81 /**
82 * Clipboard command array. May trigger changes in "cmd"
83 *
84 * @var array
85 */
86 public $CB;
87
88 /**
89 * TYPO3 Core Engine
90 *
91 * @var \TYPO3\CMS\Core\DataHandling\DataHandler
92 */
93 public $tce;
94
95 /**
96 * Constructor
97 */
98 public function __construct()
99 {
100 $GLOBALS['SOBE'] = $this;
101 $this->init();
102 }
103
104 /**
105 * Initialization of the class
106 */
107 public function init()
108 {
109 $beUser = $this->getBackendUser();
110 // GPvars:
111 $this->flags = GeneralUtility::_GP('flags');
112 $this->data = GeneralUtility::_GP('data');
113 $this->cmd = GeneralUtility::_GP('cmd');
114 $this->mirror = GeneralUtility::_GP('mirror');
115 $this->cacheCmd = GeneralUtility::_GP('cacheCmd');
116 $this->redirect = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('redirect'));
117 $this->CB = GeneralUtility::_GP('CB');
118 // Creating DataHandler object
119 $this->tce = GeneralUtility::makeInstance(DataHandler::class);
120 // Configuring based on user prefs.
121 if ($beUser->uc['recursiveDelete']) {
122 // TRUE if the delete Recursive flag is set.
123 $this->tce->deleteTree = 1;
124 }
125 if ($beUser->uc['copyLevels']) {
126 // Set to number of page-levels to copy.
127 $this->tce->copyTree = MathUtility::forceIntegerInRange($beUser->uc['copyLevels'], 0, 100);
128 }
129 if ($beUser->uc['neverHideAtCopy']) {
130 $this->tce->neverHideAtCopy = 1;
131 }
132 $TCAdefaultOverride = $beUser->getTSConfigProp('TCAdefaults');
133 if (is_array($TCAdefaultOverride)) {
134 $this->tce->setDefaultsFromUserTS($TCAdefaultOverride);
135 }
136 // Reverse order.
137 if ($this->flags['reverseOrder']) {
138 $this->tce->reverseOrder = 1;
139 }
140 }
141
142 /**
143 * Clipboard pasting and deleting.
144 */
145 public function initClipboard()
146 {
147 if (is_array($this->CB)) {
148 $clipObj = GeneralUtility::makeInstance(Clipboard::class);
149 $clipObj->initializeClipboard();
150 if ($this->CB['paste']) {
151 $clipObj->setCurrentPad($this->CB['pad']);
152 $this->cmd = $clipObj->makePasteCmdArray(
153 $this->CB['paste'],
154 $this->cmd,
155 $this->CB['update'] ?? null
156 );
157 }
158 if ($this->CB['delete']) {
159 $clipObj->setCurrentPad($this->CB['pad']);
160 $this->cmd = $clipObj->makeDeleteCmdArray($this->cmd);
161 }
162 }
163 }
164
165 /**
166 * Executing the posted actions ...
167 */
168 public function main()
169 {
170 // LOAD DataHandler with data and cmd arrays:
171 $this->tce->start($this->data, $this->cmd);
172 if (is_array($this->mirror)) {
173 $this->tce->setMirror($this->mirror);
174 }
175 // Register uploaded files
176 $this->tce->process_uploads($_FILES);
177 // Execute actions:
178 $this->tce->process_datamap();
179 $this->tce->process_cmdmap();
180 // Clearing cache:
181 if (!empty($this->cacheCmd)) {
182 $this->tce->clear_cacheCmd($this->cacheCmd);
183 }
184 // Update page tree?
185 if (isset($this->data['pages']) || isset($this->cmd['pages'])) {
186 BackendUtility::setUpdateSignal('updatePageTree');
187 }
188 }
189
190 /**
191 * Injects the request object for the current request or subrequest
192 * As this controller goes only through the main() method, it just redirects to the given URL afterwards.
193 *
194 * @param ServerRequestInterface $request the current request
195 * @param ResponseInterface $response
196 * @return ResponseInterface the response with the content
197 */
198 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
199 {
200 $this->initClipboard();
201 $this->main();
202
203 // Write errors to flash message queue
204 $this->tce->printLogErrorMessages();
205 if ($this->redirect) {
206 $response = $response
207 ->withHeader('Location', GeneralUtility::locationHeaderUrl($this->redirect))
208 ->withStatus(303);
209 }
210 return $response;
211 }
212
213 /**
214 * Processes all AJAX calls and returns a JSON formatted string
215 *
216 * @param ServerRequestInterface $request
217 * @return ResponseInterface
218 */
219 public function processAjaxRequest(ServerRequestInterface $request): ResponseInterface
220 {
221 // do the regular / main logic
222 $this->initClipboard();
223 $this->main();
224
225 /** @var \TYPO3\CMS\Core\Messaging\FlashMessageService $flashMessageService */
226 $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
227
228 $content = [
229 'redirect' => $this->redirect,
230 'messages' => [],
231 'hasErrors' => false
232 ];
233
234 // Prints errors (= write them to the message queue)
235 $this->tce->printLogErrorMessages();
236
237 $messages = $flashMessageService->getMessageQueueByIdentifier()->getAllMessagesAndFlush();
238 if (!empty($messages)) {
239 foreach ($messages as $message) {
240 $content['messages'][] = [
241 'title' => $message->getTitle(),
242 'message' => $message->getMessage(),
243 'severity' => $message->getSeverity()
244 ];
245 if ($message->getSeverity() === AbstractMessage::ERROR) {
246 $content['hasErrors'] = true;
247 }
248 }
249 }
250 return GeneralUtility::makeInstance(JsonResponse::class, $content);
251 }
252
253 /**
254 * Returns the current BE user.
255 *
256 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
257 */
258 protected function getBackendUser()
259 {
260 return $GLOBALS['BE_USER'];
261 }
262 }