[TASK] Replace sprite icon "actions-edit-undo" with IconFactory
[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\Core\Http\Response;
20 use TYPO3\CMS\Backend\Form\DataPreprocessor;
21 use TYPO3\CMS\Backend\Form\FormEngine;
22 use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
23 use TYPO3\CMS\Backend\Template\DocumentTemplate;
24 use TYPO3\CMS\Backend\Utility\BackendUtility;
25 use TYPO3\CMS\Backend\Utility\IconUtility;
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 implements \TYPO3\CMS\Core\Http\ControllerInterface {
34
35 /**
36 * Document template object
37 *
38 * @var DocumentTemplate
39 */
40 public $doc;
41
42 /**
43 * Content accumulation for the module.
44 *
45 * @var string
46 */
47 public $content;
48
49 /**
50 * Wizard parameters, coming from FormEngine linking to the wizard.
51 *
52 * @var array
53 */
54 public $P;
55
56 /**
57 * If set, launch a new window with the current records pid.
58 *
59 * @var string
60 */
61 public $popView;
62
63 /**
64 * Set to the URL of this script including variables which is needed to re-display the form. See main()
65 *
66 * @var string
67 */
68 public $R_URI;
69
70 /**
71 * Module configuration
72 *
73 * @var array
74 */
75 public $MCONF = array();
76
77 /**
78 * @var IconFactory
79 */
80 protected $iconFactory;
81
82 /**
83 * Constructor
84 */
85 public function __construct() {
86 $this->iconFactory = GeneralUtility::makeInstance(IconFactory::class);
87 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_wizards.xlf');
88 $GLOBALS['SOBE'] = $this;
89
90 $this->init();
91 }
92
93 /**
94 * Initialization of the class
95 *
96 * @return void
97 */
98 protected function init() {
99 // Setting GPvars:
100 $this->P = GeneralUtility::_GP('P');
101 $this->popView = GeneralUtility::_GP('popView');
102 $this->R_URI = GeneralUtility::linkThisScript(array('popView' => ''));
103 // "Module name":
104 $this->MCONF['name'] = 'wizard_rte';
105 // Starting the document template object:
106 $this->doc = GeneralUtility::makeInstance(DocumentTemplate::class);
107 $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/wizard_rte.html');
108 // Need to NOT have the page wrapped in DIV since if we do that we destroy
109 // the feature that the RTE spans the whole height of the page!!!
110 $this->doc->divClass = '';
111 $this->doc->form = '<form action="' . htmlspecialchars(BackendUtility::getModuleUrl('tce_db')) . '" method="post" enctype="multipart/form-data" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">';
112 }
113
114 /**
115 * Injects the request object for the current request or subrequest
116 * As this controller goes only through the main() method, it is rather simple for now
117 *
118 * @param ServerRequestInterface $request
119 * @return ResponseInterface $response
120 */
121 public function processRequest(ServerRequestInterface $request) {
122 $this->main();
123
124 /** @var Response $response */
125 $response = GeneralUtility::makeInstance(Response::class);
126 $response->getBody()->write($this->content);
127 return $response;
128 }
129
130 /**
131 * Main function, rendering the document with the iFrame with the RTE in.
132 *
133 * @return void
134 */
135 public function main() {
136 // Translate id to the workspace version:
137 if ($versionedRecord = BackendUtility::getWorkspaceVersionOfRecord($this->getBackendUserAuthentication()->workspace, $this->P['table'], $this->P['uid'], 'uid')) {
138 $this->P['uid'] = $versionedRecord['uid'];
139 }
140 // If all parameters are available:
141 if ($this->P['table'] && $this->P['field'] && $this->P['uid'] && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
142 // Getting the raw record (we need only the pid-value from here...)
143 $rawRecord = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
144 BackendUtility::fixVersioningPid($this->P['table'], $rawRecord);
145
146 // override the default jumpToUrl
147 $this->doc->JScodeArray['jumpToUrl'] = '
148 function jumpToUrl(URL,formEl) {
149 if (document.editform) {
150 if (!TBE_EDITOR.isFormChanged()) {
151 window.location.href = URL;
152 } else if (formEl) {
153 if (formEl.type=="checkbox") formEl.checked = formEl.checked ? 0 : 1;
154 }
155 } else {
156 window.location.href = URL;
157 }
158 }
159 ';
160
161 // Setting JavaScript of the pid value for viewing:
162 if ($this->popView) {
163 $this->doc->JScode = $this->doc->wrapScriptTags(BackendUtility::viewOnClick($rawRecord['pid'], '', BackendUtility::BEgetRootLine($rawRecord['pid'])));
164 }
165 // Initialize FormEngine - for rendering the field:
166 /** @var FormEngine $formEngine */
167 $formEngine = GeneralUtility::makeInstance(FormEngine::class);
168 // SPECIAL: Disables all wizards - we are NOT going to need them.
169 $formEngine->disableWizards = 1;
170 // Fetching content of record:
171 /** @var DataPreprocessor $dataPreprocessor */
172 $dataPreprocessor = GeneralUtility::makeInstance(DataPreprocessor::class);
173 $dataPreprocessor->lockRecords = 1;
174 $dataPreprocessor->fetchRecord($this->P['table'], $this->P['uid'], '');
175 // Getting the processed record content out:
176 $processedRecord = reset($dataPreprocessor->regTableItems_data);
177 $processedRecord['uid'] = $this->P['uid'];
178 $processedRecord['pid'] = $rawRecord['pid'];
179 // TSconfig, setting width:
180 $fieldTSConfig = FormEngineUtility::getTSconfigForTableRow($this->P['table'], $processedRecord, $this->P['field']);
181 if ((string)$fieldTSConfig['RTEfullScreenWidth'] !== '') {
182 $width = $fieldTSConfig['RTEfullScreenWidth'];
183 } else {
184 $width = '100%';
185 }
186 // Get the form field and wrap it in the table with the buttons:
187 $formContent = $formEngine->getSoloField($this->P['table'], $processedRecord, $this->P['field']);
188 $formContent = '
189
190 <!-- RTE wizard: -->
191 <table border="0" cellpadding="0" cellspacing="0" width="' . $width . '" id="typo3-rtewizard">
192 <tr>
193 <td width="' . $width . '" colspan="2" id="c-formContent">' . $formContent . '</td>
194 <td></td>
195 </tr>
196 </table>';
197 // Adding hidden fields:
198 $formContent .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($this->R_URI) . '" />
199 <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />' . FormEngine::getHiddenTokenField('tceAction');
200 // Finally, add the whole setup:
201 $this->content .= $formEngine->printNeededJSFunctions_top() . $formContent . $formEngine->printNeededJSFunctions();
202 } else {
203 // ERROR:
204 $this->content .= $this->doc->section($this->getLanguageService()->getLL('forms_title'), '<span class="text-danger">' . $this->getLanguageService()->getLL('table_noData', TRUE) . '</span>', 0, 1);
205 }
206 // Setting up the buttons and markers for docHeader
207 $docHeaderButtons = $this->getButtons();
208 $markers['CONTENT'] = $this->content;
209 // Build the <body> for the module
210 $this->content = $this->doc->startPage('');
211 $this->content .= $this->doc->moduleBody(array(), $docHeaderButtons, $markers);
212 $this->content .= $this->doc->endPage();
213 $this->content = $this->doc->insertStylesAndJS($this->content);
214 }
215
216 /**
217 * Outputting the accumulated content to screen
218 *
219 * @return void
220 * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8, use processRequest() instead
221 */
222 public function printContent() {
223 GeneralUtility::logDeprecatedFunction();
224 echo $this->content;
225 }
226
227 /**
228 * Create the panel of buttons for submitting the form or otherwise perform operations.
229 *
230 * @return array All available buttons as an assoc. array
231 */
232 protected function getButtons() {
233 $buttons = array(
234 'close' => '',
235 'save' => '',
236 'save_view' => '',
237 'save_close' => '',
238 'shortcut' => '',
239 'undo' => ''
240 );
241 if ($this->P['table'] && $this->P['field'] && $this->P['uid'] && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
242 $closeUrl = GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']);
243 // Getting settings for the undo button:
244 $undoButton = 0;
245 $databaseConnection = $this->getDatabaseConnection();
246 $undoRes = $databaseConnection->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $databaseConnection->fullQuoteStr($this->P['table'], 'sys_history') . ' AND recuid=' . (int)$this->P['uid'], '', 'tstamp DESC', '1');
247 if ($undoButtonR = $databaseConnection->sql_fetch_assoc($undoRes)) {
248 $undoButton = 1;
249 }
250 // Close
251 $buttons['close'] = '<a href="#" onclick="' . htmlspecialchars('jumpToUrl(' . GeneralUtility::quoteJSvalue($closeUrl) . '); return false;') . '" title="' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE) . '">' . $this->iconFactory->getIcon('actions-document-close', Icon::SIZE_SMALL) . '</a>';
252 // Save
253 $buttons['save'] = '<button class="c-inputButton" name="_savedok_x" onclick="TBE_EDITOR.checkAndDoSubmit(1); return false;">'
254 . IconUtility::getSpriteIcon('actions-document-save', array('title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', TRUE)))
255 . '</button>';
256 // Save & View
257 $buttons['save_view'] = '<button class="c-inputButton" name="_savedokview_x" onclick="' . htmlspecialchars('document.editform.redirect.value+=\'&popView=1\'; TBE_EDITOR.checkAndDoSubmit(1); return false;') . '">'
258 . IconUtility::getSpriteIcon('actions-document-save-view', array('title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDocShow', TRUE)))
259 . '</button>';
260 // Save & Close
261 $buttons['save_close'] = '<button class="c-inputButton" name="_saveandclosedok_x" onclick="' . htmlspecialchars('document.editform.redirect.value=' . GeneralUtility::quoteJSvalue($closeUrl) . '; TBE_EDITOR.checkAndDoSubmit(1); return false;') . '">'
262 . IconUtility::getSpriteIcon('actions-document-save-close', array('title' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc', TRUE)))
263 . '</button>';
264 // Undo/Revert:
265 if ($undoButton) {
266 $aOnClick = 'window.location.href=' .
267 GeneralUtility::quoteJSvalue(
268 BackendUtility::getModuleUrl(
269 'record_history',
270 array(
271 'element' => $this->P['table'] . ':' . $this->P['uid'],
272 'revert' => 'field:' . $this->P['field'],
273 'sumUp' => -1,
274 'returnUrl' => $this->R_URI,
275 )
276 )
277 ) . '; return false;';
278 $buttons['undo'] = '<a href="#" onclick="' . htmlspecialchars($aOnClick) . '"' . ' title="' . htmlspecialchars(sprintf($this->getLanguageService()->getLL('undoLastChange'), BackendUtility::calcAge(($GLOBALS['EXEC_TIME'] - $undoButtonR['tstamp']), $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')))) . '">' . $this->iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL) . '</a>';
279 }
280 // Shortcut
281 if ($this->getBackendUserAuthentication()->mayMakeShortcut()) {
282 $buttons['shortcut'] = $this->doc->makeShortcutIcon('P', '', $this->MCONF['name'], 1);
283 }
284 }
285 return $buttons;
286 }
287
288 }