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