[TASK] Remove usage of setForm from RteController
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / Wizard / RteController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller\Wizard;
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 Psr\Http\Message\ResponseInterface;
19 use TYPO3\CMS\Backend\Form\FormDataCompiler;
20 use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord;
21 use TYPO3\CMS\Backend\Form\FormResultCompiler;
22 use TYPO3\CMS\Backend\Form\NodeFactory;
23 use TYPO3\CMS\Backend\Form\FormEngine;
24 use TYPO3\CMS\Backend\Template\Components\ButtonBar;
25 use TYPO3\CMS\Backend\Utility\BackendUtility;
26 use TYPO3\CMS\Core\Imaging\Icon;
27 use TYPO3\CMS\Core\Imaging\IconFactory;
28 use TYPO3\CMS\Core\Utility\GeneralUtility;
29
30 /**
31 * Script class for rendering the full screen RTE display
32 */
33 class RteController extends AbstractWizardController
34 {
35 /**
36 * Content accumulation for the module.
37 *
38 * @var string
39 */
40 public $content;
41
42 /**
43 * Wizard parameters, coming from FormEngine linking to the wizard.
44 *
45 * @var array
46 */
47 public $P;
48
49 /**
50 * If set, launch a new window with the current records pid.
51 *
52 * @var string
53 */
54 public $popView;
55
56 /**
57 * Set to the URL of this script including variables which is needed to re-display the form. See main()
58 *
59 * @var string
60 */
61 public $R_URI;
62
63 /**
64 * Module configuration
65 *
66 * @var array
67 */
68 public $MCONF = array();
69
70 /**
71 * Constructor
72 */
73 public function __construct()
74 {
75 parent::__construct();
76 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
77 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_wizards.xlf');
78 $GLOBALS['SOBE'] = $this;
79
80 $this->init();
81 }
82
83 /**
84 * Initialization of the class
85 *
86 * @return void
87 */
88 protected function init()
89 {
90 // Setting GPvars:
91 $this->P = GeneralUtility::_GP('P');
92 $this->popView = GeneralUtility::_GP('popView');
93 $this->R_URI = GeneralUtility::linkThisScript(array('popView' => ''));
94 // "Module name":
95 $this->MCONF['name'] = 'wizard_rte';
96 // Need to NOT have the page wrapped in DIV since if we do that we destroy
97 // the feature that the RTE spans the whole height of the page!!!
98 }
99
100 /**
101 * Injects the request object for the current request or subrequest
102 * As this controller goes only through the main() method, it is rather simple for now
103 *
104 * @param ServerRequestInterface $request
105 * @param ResponseInterface $response
106 * @return ResponseInterface
107 */
108 public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
109 {
110 $this->main();
111
112 $response->getBody()->write($this->moduleTemplate->renderContent());
113 return $response;
114 }
115
116 /**
117 * Main function, rendering the document with the iFrame with the RTE in.
118 *
119 * @return void
120 */
121 public function main()
122 {
123 $this->content .= '<form action="'
124 . htmlspecialchars(BackendUtility::getModuleUrl('tce_db'))
125 . '" method="post" enctype="multipart/form-data" id="RteController" name="editform" '
126 . ' onsubmit="return TBE_EDITOR.checkSubmit(1);">';
127 // Translate id to the workspace version:
128 if ($versionedRecord = BackendUtility::getWorkspaceVersionOfRecord(
129 $this->getBackendUserAuthentication()->workspace,
130 $this->P['table'],
131 $this->P['uid'],
132 'uid'
133 )) {
134 $this->P['uid'] = $versionedRecord['uid'];
135 }
136 // If all parameters are available:
137 if ($this->P['table']
138 && $this->P['field']
139 && $this->P['uid']
140 && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
141 /** @var TcaDatabaseRecord $formDataGroup */
142 $formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);
143 /** @var FormDataCompiler $formDataCompiler */
144 $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
145 /** @var NodeFactory $nodeFactory */
146 $nodeFactory = GeneralUtility::makeInstance(NodeFactory::class);
147
148 $formDataCompilerInput = [
149 'vanillaUid' => (int)$this->P['uid'],
150 'tableName' => $this->P['table'],
151 'command' => 'edit',
152 'disabledWizards' => true,
153 ];
154
155 $formData = $formDataCompiler->compile($formDataCompilerInput);
156
157 $formData['fieldListToRender'] = $this->P['field'];
158 $formData['renderType'] = 'outerWrapContainer';
159 $formResult = $nodeFactory->create($formData)->render();
160
161 /** @var FormResultCompiler $formResultCompiler */
162 $formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
163 $formResultCompiler->mergeResult($formResult);
164
165 // override the default jumpToUrl
166 $this->moduleTemplate->addJavaScriptCode(
167 'RteWizardInlineCode',
168 'function jumpToUrl(URL,formEl) {
169 if (document.editform) {
170 if (!TBE_EDITOR.isFormChanged()) {
171 window.location.href = URL;
172 } else if (formEl) {
173 if (formEl.type=="checkbox") formEl.checked = formEl.checked ? 0 : 1;
174 }
175 } else {
176 window.location.href = URL;
177 }
178 }
179 '
180 );
181
182 // Setting JavaScript of the pid value for viewing:
183 if ($this->popView) {
184 $this->moduleTemplate->addJavaScriptCode(
185 'PopupViewInlineJS',
186 BackendUtility::viewOnClick(
187 $formData['databaseRow']['pid'],
188 '',
189 BackendUtility::BEgetRootLine($formData['databaseRow']['pid'])
190 )
191 );
192 }
193
194 $pageTsConfigMerged = $formData['pageTsConfigMerged'];
195 if ((string)$pageTsConfigMerged['TCEFORM.'][$this->P['table'] . '.'][$this->P['field'] . '.']['RTEfullScreenWidth'] !== '') {
196 $width = (string)$pageTsConfigMerged['TCEFORM.'][$this->P['table'] . '.'][$this->P['field'] . '.']['RTEfullScreenWidth'];
197 } else {
198 $width = '100%';
199 }
200 // Get the form field and wrap it in the table with the buttons:
201 $formContent = $formResult['html'];
202 $formContent = '
203 <table border="0" cellpadding="0" cellspacing="0" width="' . $width . '" id="typo3-rtewizard">
204 <tr>
205 <td width="' . $width . '" colspan="2" id="c-formContent">' . $formContent . '</td>
206 <td></td>
207 </tr>
208 </table>';
209
210 // Adding hidden fields:
211 $formContent .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($this->R_URI) . '" />
212 <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />';
213 // Finally, add the whole setup:
214 $this->content .= $formResultCompiler->JStop()
215 . $formContent
216 . $formResultCompiler->printNeededJSFunctions();
217 } else {
218 // ERROR:
219 $this->content .= $this->moduleTemplate->section(
220 $this->getLanguageService()->getLL('forms_title'),
221 '<span class="text-danger">'
222 . $this->getLanguageService()->getLL('table_noData', true)
223 . '</span>',
224 0,
225 1
226 );
227 }
228 // Setting up the buttons and markers for docHeader
229 $this->getButtons();
230 // Build the <body> for the module
231 $this->moduleTemplate->setContent($this->content);
232 }
233
234 /**
235 * Outputting the accumulated content to screen
236 *
237 * @return void
238 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use mainAction() instead
239 */
240 public function printContent()
241 {
242 GeneralUtility::logDeprecatedFunction();
243 echo $this->content;
244 }
245
246 /**
247 * Create the panel of buttons for submitting the form or otherwise perform operations.
248 *
249 * @return array All available buttons as an assoc. array
250 */
251 protected function getButtons()
252 {
253 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
254 if ($this->P['table']
255 && $this->P['field']
256 && $this->P['uid']
257 && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
258 $closeUrl = GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']);
259 // Getting settings for the undo button:
260 $undoButton = 0;
261 $databaseConnection = $this->getDatabaseConnection();
262 $undoRes = $databaseConnection->exec_SELECTquery(
263 'tstamp',
264 'sys_history',
265 'tablename=' . $databaseConnection->fullQuoteStr(
266 $this->P['table'],
267 'sys_history'
268 ) . ' AND recuid=' . (int)$this->P['uid'],
269 '',
270 'tstamp DESC',
271 '1'
272 );
273 if ($undoButtonR = $databaseConnection->sql_fetch_assoc($undoRes)) {
274 $undoButton = 1;
275 }
276
277 // Close
278 $closeButton = $buttonBar->makeLinkButton()
279 ->setHref($closeUrl)
280 ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', true))
281 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-close', Icon::SIZE_SMALL));
282 $buttonBar->addButton($closeButton, ButtonBar::BUTTON_POSITION_LEFT, 10);
283
284 // Save
285 $saveButton = $buttonBar->makeInputButton()
286 ->setName('_savedok_x')
287 ->setValue('1')
288 ->setForm('RteController')
289 ->setOnClick('TBE_EDITOR.checkAndDoSubmit(1); return false;')
290 ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', true))
291 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save', Icon::SIZE_SMALL));
292 // Save & View
293 $saveAndViewButton = $buttonBar->makeInputButton()
294 ->setName('_savedokview_x')
295 ->setValue('1')
296 ->setForm('RteController')
297 ->setOnClick('document.editform.redirect.value+= ' . GeneralUtility::quoteJSvalue('&popView=1') . '; '
298 . ' TBE_EDITOR.checkAndDoSubmit(1); return false;')
299 ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDocShow', true))
300 ->setIcon(
301 $this->moduleTemplate->getIconFactory()->getIcon('actions-document-save-view', Icon::SIZE_SMALL)
302 );
303
304 // Save & Close
305 $saveAndCloseButton = $buttonBar->makeInputButton()
306 ->setName('_saveandclosedok_x')
307 ->setValue('1')
308 ->setForm('RteController')
309 ->setOnClick('document.editform.redirect.value=' . GeneralUtility::quoteJSvalue($closeUrl)
310 . '; TBE_EDITOR.checkAndDoSubmit(1); return false;')
311 ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc', true))
312 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
313 'actions-document-save-close',
314 Icon::SIZE_SMALL
315 ));
316
317 // Save SplitButton
318 $saveSplitButton = $buttonBar->makeSplitButton()
319 ->addItem($saveButton)
320 ->addItem($saveAndViewButton)
321 ->addItem($saveAndCloseButton);
322 $buttonBar->addButton($saveSplitButton, ButtonBar::BUTTON_POSITION_LEFT, 20);
323
324 // Undo/Revert:
325 if ($undoButton) {
326 $aOnClick = 'window.location.href=' .
327 GeneralUtility::quoteJSvalue(
328 BackendUtility::getModuleUrl(
329 'record_history',
330 array(
331 'element' => $this->P['table'] . ':' . $this->P['uid'],
332 'revert' => 'field:' . $this->P['field'],
333 'sumUp' => -1,
334 'returnUrl' => $this->R_URI,
335 )
336 )
337 ) . '; return false;';
338
339 $undoText = $this->getLanguageService()->sL(
340 'LLL:EXT:lang/locallang_wizards.xlf:rte_undoLastChange'
341 );
342 $lastChangeLabel = sprintf(
343 $undoText,
344 BackendUtility::calcAge(
345 ($GLOBALS['EXEC_TIME'] - $undoButtonR['tstamp']),
346 $this->getLanguageService()->sL(
347 'LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears'
348 )
349 )
350 );
351
352 $undoRevertButton = $buttonBar->makeLinkButton()
353 ->setHref('#')
354 ->setOnClick($aOnClick)
355 ->setTitle($lastChangeLabel)
356 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-edit-undo', Icon::SIZE_SMALL));
357 $buttonBar->addButton($undoRevertButton, ButtonBar::BUTTON_POSITION_LEFT, 30);
358 }
359 // Shortcut
360 $shortButton = $buttonBar->makeShortcutButton()
361 ->setModuleName($this->MCONF['name'])
362 ->setGetVariables(['P']);
363 $buttonBar->addButton($shortButton);
364 }
365 }
366 }