[FEATURE] Introduce AJAX functionality for list module
[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 TYPO3\CMS\Core\Utility\GeneralUtility;
18
19 /**
20 * Script Class, creating object of \TYPO3\CMS\Core\DataHandling\DataHandler and
21 * sending the posted data to the object.
22 *
23 * Used by many smaller forms/links in TYPO3, including the QuickEdit module.
24 * Is not used by alt_doc.php though (main form rendering script) - that uses the same class (TCEmain) but makes its own initialization (to save the redirect request).
25 * For all other cases than alt_doc.php 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 alt_doc.php, that will give you easy form-rendering as well.
26 *
27 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
28 */
29 class SimpleDataHandlerController {
30
31 /**
32 * Array. Accepts options to be set in TCE object. Currently it supports "reverseOrder" (bool).
33 *
34 * @var array
35 */
36 public $flags;
37
38 /**
39 * Data array on the form [tablename][uid][fieldname] = value
40 *
41 * @var array
42 */
43 public $data;
44
45 /**
46 * Command array on the form [tablename][uid][command] = value.
47 * This array may get additional data set internally based on clipboard commands send in CB var!
48 *
49 * @var array
50 */
51 public $cmd;
52
53 /**
54 * Array passed to ->setMirror.
55 *
56 * @var array
57 */
58 public $mirror;
59
60 /**
61 * Cache command sent to ->clear_cacheCmd
62 *
63 * @var string
64 */
65 public $cacheCmd;
66
67 /**
68 * Redirect URL. Script will redirect to this location after performing operations (unless errors has occurred)
69 *
70 * @var string
71 */
72 public $redirect;
73
74 /**
75 * 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.
76 *
77 * @var int
78 */
79 public $prErr;
80
81 /**
82 * Clipboard command array. May trigger changes in "cmd"
83 *
84 * @var array
85 */
86 public $CB;
87
88 /**
89 * Verification code
90 *
91 * @var string
92 */
93 public $vC;
94
95 /**
96 * Boolean. Update Page Tree Trigger. If set and the manipulated records are pages then the update page tree signal will be set.
97 *
98 * @var int
99 */
100 public $uPT;
101
102 /**
103 * String, general comment (for raising stages of workspace versions)
104 *
105 * @var string
106 */
107 public $generalComment;
108
109 /**
110 * Files to include after init() function is called:
111 *
112 * @var array
113 */
114 public $include_once = array();
115
116 /**
117 * TYPO3 Core Engine
118 *
119 * @var \TYPO3\CMS\Core\DataHandling\DataHandler
120 */
121 public $tce;
122
123 /**
124 * Constructor
125 */
126 public function __construct() {
127 $GLOBALS['SOBE'] = $this;
128 $this->init();
129 }
130
131 /**
132 * Initialization of the class
133 *
134 * @return void
135 */
136 public function init() {
137 // GPvars:
138 $this->flags = GeneralUtility::_GP('flags');
139 $this->data = GeneralUtility::_GP('data');
140 $this->cmd = GeneralUtility::_GP('cmd');
141 $this->mirror = GeneralUtility::_GP('mirror');
142 $this->cacheCmd = GeneralUtility::_GP('cacheCmd');
143 $this->redirect = GeneralUtility::sanitizeLocalUrl(GeneralUtility::_GP('redirect'));
144 $this->prErr = GeneralUtility::_GP('prErr');
145 $this->_disableRTE = GeneralUtility::_GP('_disableRTE');
146 $this->CB = GeneralUtility::_GP('CB');
147 $this->vC = GeneralUtility::_GP('vC');
148 $this->uPT = GeneralUtility::_GP('uPT');
149 $this->generalComment = GeneralUtility::_GP('generalComment');
150 // Creating TCEmain object
151 $this->tce = GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
152 $this->tce->stripslashes_values = 0;
153 $this->tce->generalComment = $this->generalComment;
154 // Configuring based on user prefs.
155 if ($GLOBALS['BE_USER']->uc['recursiveDelete']) {
156 // TRUE if the delete Recursive flag is set.
157 $this->tce->deleteTree = 1;
158 }
159 if ($GLOBALS['BE_USER']->uc['copyLevels']) {
160 // Set to number of page-levels to copy.
161 $this->tce->copyTree = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($GLOBALS['BE_USER']->uc['copyLevels'], 0, 100);
162 }
163 if ($GLOBALS['BE_USER']->uc['neverHideAtCopy']) {
164 $this->tce->neverHideAtCopy = 1;
165 }
166 $TCAdefaultOverride = $GLOBALS['BE_USER']->getTSConfigProp('TCAdefaults');
167 if (is_array($TCAdefaultOverride)) {
168 $this->tce->setDefaultsFromUserTS($TCAdefaultOverride);
169 }
170 // Reverse order.
171 if ($this->flags['reverseOrder']) {
172 $this->tce->reverseOrder = 1;
173 }
174 }
175
176 /**
177 * Clipboard pasting and deleting.
178 *
179 * @return void
180 */
181 public function initClipboard() {
182 if (is_array($this->CB)) {
183 $clipObj = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Clipboard\Clipboard::class);
184 $clipObj->initializeClipboard();
185 if ($this->CB['paste']) {
186 $clipObj->setCurrentPad($this->CB['pad']);
187 $this->cmd = $clipObj->makePasteCmdArray(
188 $this->CB['paste'],
189 $this->cmd,
190 isset($this->CB['update']) ? $this->CB['update'] : NULL
191 );
192 }
193 if ($this->CB['delete']) {
194 $clipObj->setCurrentPad($this->CB['pad']);
195 $this->cmd = $clipObj->makeDeleteCmdArray($this->cmd);
196 }
197 }
198 }
199
200 /**
201 * Executing the posted actions ...
202 *
203 * @return void
204 */
205 public function main() {
206 // LOAD TCEmain with data and cmd arrays:
207 $this->tce->start($this->data, $this->cmd);
208 if (is_array($this->mirror)) {
209 $this->tce->setMirror($this->mirror);
210 }
211 // Checking referer / executing
212 $refInfo = parse_url(GeneralUtility::getIndpEnv('HTTP_REFERER'));
213 $httpHost = GeneralUtility::getIndpEnv('TYPO3_HOST_ONLY');
214 if ($httpHost != $refInfo['host'] && $this->vC != $GLOBALS['BE_USER']->veriCode() && !$GLOBALS['TYPO3_CONF_VARS']['SYS']['doNotCheckReferer']) {
215 $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));
216 } else {
217 // Register uploaded files
218 $this->tce->process_uploads($_FILES);
219 // Execute actions:
220 $this->tce->process_datamap();
221 $this->tce->process_cmdmap();
222 // Clearing cache:
223 if (!empty($this->cacheCmd)) {
224 $this->tce->clear_cacheCmd($this->cacheCmd);
225 }
226 // Update page tree?
227 if ($this->uPT && (isset($this->data['pages']) || isset($this->cmd['pages']))) {
228 \TYPO3\CMS\Backend\Utility\BackendUtility::setUpdateSignal('updatePageTree');
229 }
230 }
231 }
232
233 /**
234 * Redirecting the user after the processing has been done.
235 * Might also display error messages directly, if any.
236 *
237 * @return void
238 */
239 public function finish() {
240 // Prints errors, if...
241 if ($this->prErr) {
242 $this->tce->printLogErrorMessages($this->redirect);
243 }
244 if ($this->redirect && !$this->tce->debug) {
245 \TYPO3\CMS\Core\Utility\HttpUtility::redirect($this->redirect);
246 }
247 }
248
249 /**
250 * Processes all AJAX calls and returns a JSON formatted string
251 *
252 * @param array $parameters
253 * @param \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxRequestHandler
254 */
255 public function processAjaxRequest($parameters, \TYPO3\CMS\Core\Http\AjaxRequestHandler $ajaxRequestHandler) {
256 // do the regular / main logic
257 $this->initClipboard();
258 $this->main();
259
260 $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
261
262 $content = array(
263 'redirect' => $this->redirect,
264 'messages' => array(),
265 'hasErrors' => FALSE
266 );
267
268 // Prints errors (= write them to the message queue)
269 if ($this->prErr) {
270 $content['hasErrors'] = TRUE;
271 $this->tce->printLogErrorMessages($this->redirect);
272 }
273
274 $messages = $flashMessageService->getMessageQueueByIdentifier()->getAllMessagesAndFlush();
275 if (!empty($messages)) {
276 foreach ($messages as $message) {
277 $content['messages'][] = array(
278 'title' => $message->getTitle(),
279 'message' => $message->getMessage(),
280 'severity' => $message->getSeverity()
281 );
282 }
283 }
284 $ajaxRequestHandler->setContentFormat('json');
285 $ajaxRequestHandler->setContent($content);
286 }
287 }