Revert "[TASK] Rebuild the calcAge functionality"
[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 TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Backend\Utility\IconUtility;
19 use TYPO3\CMS\Core\Utility\GeneralUtility;
20
21 /**
22 * Script Class for rendering the full screen RTE display
23 *
24 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
25 */
26 class RteController {
27
28 // Internal, dynamic:
29 /**
30 * document template object
31 *
32 * @var \TYPO3\CMS\Backend\Template\DocumentTemplate
33 * @todo Define visibility
34 */
35 public $doc;
36
37 // Content accumulation for the module.
38 /**
39 * @todo Define visibility
40 */
41 public $content;
42
43 // Internal, static: GPvars
44 // Wizard parameters, coming from TCEforms linking to the wizard.
45 /**
46 * @todo Define visibility
47 */
48 public $P;
49
50 // If set, launch a new window with the current records pid.
51 /**
52 * @todo Define visibility
53 */
54 public $popView;
55
56 // Set to the URL of this script including variables which is needed to re-display the form. See main()
57 /**
58 * @todo Define visibility
59 */
60 public $R_URI;
61
62 /**
63 * Constructor
64 */
65 public function __construct() {
66 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_wizards.xlf');
67 $GLOBALS['SOBE'] = $this;
68
69 $this->init();
70 }
71
72 /**
73 * Initialization of the class
74 *
75 * @return void
76 */
77 protected function init() {
78 // Setting GPvars:
79 $this->P = GeneralUtility::_GP('P');
80 $this->popView = GeneralUtility::_GP('popView');
81 $this->R_URI = GeneralUtility::linkThisScript(array('popView' => ''));
82 // "Module name":
83 $this->MCONF['name'] = 'wizard_rte';
84 // Starting the document template object:
85 $this->doc = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate');
86 $this->doc->backPath = $GLOBALS['BACK_PATH'];
87 $this->doc->setModuleTemplate('EXT:backend/Resources/Private/Templates/wizard_rte.html');
88 // Need to NOT have the page wrapped in DIV since if we do that we destroy
89 // the feature that the RTE spans the whole height of the page!!!
90 $this->doc->divClass = '';
91 $this->doc->form = '<form action="tce_db.php" method="post" enctype="' . $GLOBALS['TYPO3_CONF_VARS']['SYS']['form_enctype'] . '" name="editform" onsubmit="return TBE_EDITOR.checkSubmit(1);">';
92 }
93
94 /**
95 * Main function, rendering the document with the iframe with the RTE in.
96 *
97 * @return void
98 */
99 public function main() {
100 // Translate id to the workspace version:
101 if ($versionRec = BackendUtility::getWorkspaceVersionOfRecord($GLOBALS['BE_USER']->workspace, $this->P['table'], $this->P['uid'], 'uid')) {
102 $this->P['uid'] = $versionRec['uid'];
103 }
104 // If all parameters are available:
105 if ($this->P['table'] && $this->P['field'] && $this->P['uid'] && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
106 // Getting the raw record (we need only the pid-value from here...)
107 $rawRec = BackendUtility::getRecord($this->P['table'], $this->P['uid']);
108 BackendUtility::fixVersioningPid($this->P['table'], $rawRec);
109
110 // override the default jumpToUrl
111 $this->doc->JScodeArray['jumpToUrl'] = '
112 function jumpToUrl(URL,formEl) {
113 if (document.editform) {
114 if (!TBE_EDITOR.isFormChanged()) {
115 window.location.href = URL;
116 } else if (formEl) {
117 if (formEl.type=="checkbox") formEl.checked = formEl.checked ? 0 : 1;
118 }
119 } else {
120 window.location.href = URL;
121 }
122 }
123 ';
124
125 // Setting JavaScript of the pid value for viewing:
126 if ($this->popView) {
127 $this->doc->JScode = $this->doc->wrapScriptTags(BackendUtility::viewOnClick($rawRec['pid'], '', BackendUtility::BEgetRootLine($rawRec['pid'])));
128 }
129 // Initialize TCeforms - for rendering the field:
130 $tceforms = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\FormEngine');
131 // Init...
132 $tceforms->initDefaultBEMode();
133 // SPECIAL: Disables all wizards - we are NOT going to need them.
134 $tceforms->disableWizards = 1;
135 // SPECIAL: Setting background color of the RTE to ordinary background
136 $tceforms->colorScheme[0] = $this->doc->bgColor;
137 // Initialize style for RTE object:
138 // Getting reference to the RTE object used to render the field!
139 $RTEobj = BackendUtility::RTEgetObj();
140 if ($RTEobj->ID == 'rte') {
141 $RTEobj->RTEdivStyle = 'position:relative; left:0px; top:0px; height:100%; width:100%; border:solid 0px;';
142 }
143 // Fetching content of record:
144 $trData = GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Form\\DataPreprocessor');
145 $trData->lockRecords = 1;
146 $trData->fetchRecord($this->P['table'], $this->P['uid'], '');
147 // Getting the processed record content out:
148 $rec = reset($trData->regTableItems_data);
149 $rec['uid'] = $this->P['uid'];
150 $rec['pid'] = $rawRec['pid'];
151 // TSconfig, setting width:
152 $fieldTSConfig = $tceforms->setTSconfig($this->P['table'], $rec, $this->P['field']);
153 if ((string)$fieldTSConfig['RTEfullScreenWidth'] !== '') {
154 $width = $fieldTSConfig['RTEfullScreenWidth'];
155 } else {
156 $width = '100%';
157 }
158 // Get the form field and wrap it in the table with the buttons:
159 $formContent = $tceforms->getSoloField($this->P['table'], $rec, $this->P['field']);
160 $formContent = '
161
162
163 <!--
164 RTE wizard:
165 -->
166 <table border="0" cellpadding="0" cellspacing="0" width="' . $width . '" id="typo3-rtewizard">
167 <tr>
168 <td width="' . $width . '" colspan="2" id="c-formContent">' . $formContent . '</td>
169 <td></td>
170 </tr>
171 </table>';
172 // Adding hidden fields:
173 $formContent .= '<input type="hidden" name="redirect" value="' . htmlspecialchars($this->R_URI) . '" />
174 <input type="hidden" name="_serialNumber" value="' . md5(microtime()) . '" />' . \TYPO3\CMS\Backend\Form\FormEngine::getHiddenTokenField('tceAction');
175 // Finally, add the whole setup:
176 $this->content .= $tceforms->printNeededJSFunctions_top() . $formContent . $tceforms->printNeededJSFunctions();
177 } else {
178 // ERROR:
179 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('forms_title'), '<span class="typo3-red">' . $GLOBALS['LANG']->getLL('table_noData', TRUE) . '</span>', 0, 1);
180 }
181 // Setting up the buttons and markers for docheader
182 $docHeaderButtons = $this->getButtons();
183 $markers['CONTENT'] = $this->content;
184 // Build the <body> for the module
185 $this->content = $this->doc->startPage('');
186 $this->content .= $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
187 $this->content .= $this->doc->endPage();
188 $this->content = $this->doc->insertStylesAndJS($this->content);
189 }
190
191 /**
192 * Outputting the accumulated content to screen
193 *
194 * @return void
195 * @todo Define visibility
196 */
197 public function printContent() {
198 $this->content .= $this->doc->endPage();
199 $this->content = $this->doc->insertStylesAndJS($this->content);
200 echo $this->content;
201 }
202
203 /**
204 * Create the panel of buttons for submitting the form or otherwise perform operations.
205 *
206 * @return array All available buttons as an assoc. array
207 */
208 protected function getButtons() {
209 $buttons = array(
210 'close' => '',
211 'save' => '',
212 'save_view' => '',
213 'save_close' => '',
214 'shortcut' => '',
215 'undo' => ''
216 );
217 if ($this->P['table'] && $this->P['field'] && $this->P['uid'] && $this->checkEditAccess($this->P['table'], $this->P['uid'])) {
218 $closeUrl = GeneralUtility::sanitizeLocalUrl($this->P['returnUrl']);
219 // Getting settings for the undo button:
220 $undoButton = 0;
221 $undoRes = $GLOBALS['TYPO3_DB']->exec_SELECTquery('tstamp', 'sys_history', 'tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->P['table'], 'sys_history') . ' AND recuid=' . (int)$this->P['uid'], '', 'tstamp DESC', '1');
222 if ($undoButtonR = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($undoRes)) {
223 $undoButton = 1;
224 }
225 // Close
226 $buttons['close'] = '<a href="#" onclick="' . htmlspecialchars(('jumpToUrl(unescape(\'' . rawurlencode($closeUrl) . '\')); return false;')) . '">' . '<img' . IconUtility::skinImg($this->doc->backPath, 'gfx/closedok.gif') . ' class="c-inputButton" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.closeDoc', TRUE) . '" alt="" />' . '</a>';
227 // Save
228 $buttons['save'] = '<a href="#" onclick="TBE_EDITOR.checkAndDoSubmit(1); return false;">' . '<img' . IconUtility::skinImg($this->doc->backPath, 'gfx/savedok.gif') . ' class="c-inputButton" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDoc', TRUE) . '" alt="" />' . '</a>';
229 // Save & View
230 $buttons['save_view'] = '<a href="#" onclick="' . htmlspecialchars('document.editform.redirect.value+=\'&popView=1\'; TBE_EDITOR.checkAndDoSubmit(1); return false;') . '">' . '<img' . IconUtility::skinImg($this->doc->backPath, 'gfx/savedokshow.gif') . ' class="c-inputButton" title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveDocShow', TRUE) . '" alt="" />' . '</a>';
231 // Save & Close
232 $buttons['save_close'] = '<input type="image" class="c-inputButton" onclick="' . htmlspecialchars(('document.editform.redirect.value=\'' . $closeUrl . '\'; TBE_EDITOR.checkAndDoSubmit(1); return false;')) . '" name="_saveandclosedok"' . IconUtility::skinImg($this->doc->backPath, 'gfx/saveandclosedok.gif', '') . ' title="' . $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:rm.saveCloseDoc', TRUE) . '" />';
233 // Undo/Revert:
234 if ($undoButton) {
235 $buttons['undo'] = '<a href="#" onclick="' . htmlspecialchars('window.location.href=' .
236 GeneralUtility::quoteJSvalue(
237 BackendUtility::getModuleUrl(
238 'record_history',
239 array(
240 'element' => $this->P['table'] . ':' . $this->P['uid'],
241 'revert' => 'field:' . $this->P['field'],
242 'sumUp' => -1,
243 'returnUrl' => $this->R_URI,
244 )
245 )
246 ) . '; return false;') . '">' . '<img' . IconUtility::skinImg($this->doc->backPath, 'gfx/undo.gif') . ' class="c-inputButton" title="' . htmlspecialchars(sprintf($GLOBALS['LANG']->getLL('rte_undoLastChange'), BackendUtility::calcAge(($GLOBALS['EXEC_TIME'] - $undoButtonR['tstamp']), $GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xlf:labels.minutesHoursDaysYears')))) . '" alt="" />' . '</a>';
247 }
248 // Shortcut
249 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
250 $buttons['shortcut'] = $this->doc->makeShortcutIcon('P', '', $this->MCONF['name'], 1);
251 }
252 }
253 return $buttons;
254 }
255
256 /**
257 * Checks access for element
258 *
259 * @param string $table Table name
260 * @param integer $uid Record uid
261 * @return boolean
262 * @todo Define visibility
263 * @todo: Refactor to remove duplicate code (see FormsController, TableController)
264 */
265 public function checkEditAccess($table, $uid) {
266 $calcPRec = BackendUtility::getRecord($table, $uid);
267 BackendUtility::fixVersioningPid($table, $calcPRec);
268 if (is_array($calcPRec)) {
269 // If pages:
270 if ($table == 'pages') {
271 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms($calcPRec);
272 $hasAccess = $CALC_PERMS & 2 ? TRUE : FALSE;
273 } else {
274 // Fetching pid-record first.
275 $CALC_PERMS = $GLOBALS['BE_USER']->calcPerms(BackendUtility::getRecord('pages', $calcPRec['pid']));
276 $hasAccess = $CALC_PERMS & 16 ? TRUE : FALSE;
277 }
278 // Check internals regarding access:
279 if ($hasAccess) {
280 $hasAccess = $GLOBALS['BE_USER']->recordEditAccessInternals($table, $calcPRec);
281 }
282 } else {
283 $hasAccess = FALSE;
284 }
285 return $hasAccess;
286 }
287
288 }