19f54821204d053067b501a147a8e049eb375d08
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / Classes / Controller / FrontendRteController.php
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2005-2013 Stanislas Rolland <typo3(arobas)sjbr.ca>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the text file GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Front end RTE based on htmlArea
31 *
32 * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
33 */
34 class FrontendRteController extends \TYPO3\CMS\Rtehtmlarea\RteHtmlAreaBase {
35
36 // External:
37 public $RTEWrapStyle = '';
38
39 // Alternative style for RTE wrapper <div> tag.
40 public $RTEdivStyle = '';
41
42 // Alternative style for RTE <div> tag.
43 // For the editor
44 /**
45 * @todo Define visibility
46 */
47 public $elementId;
48
49 /**
50 * @todo Define visibility
51 */
52 public $elementParts;
53
54 /**
55 * @todo Define visibility
56 */
57 public $tscPID;
58
59 /**
60 * @todo Define visibility
61 */
62 public $typeVal;
63
64 /**
65 * @todo Define visibility
66 */
67 public $thePid;
68
69 /**
70 * @todo Define visibility
71 */
72 public $RTEsetup = array();
73
74 /**
75 * @todo Define visibility
76 */
77 public $thisConfig = array();
78
79 /**
80 * @todo Define visibility
81 */
82 public $confValues;
83
84 public $language;
85
86 public $OutputCharset;
87
88 /**
89 * @todo Define visibility
90 */
91 public $specConf;
92
93 /**
94 * @todo Define visibility
95 */
96 public $LOCAL_LANG;
97
98 /**
99 * @var \TYPO3\CMS\Core\Page\PageRenderer
100 */
101 protected $pageRenderer;
102
103 /**
104 * Draws the RTE as an iframe
105 *
106 * @param object Reference to parent object, which is an instance of the TCEforms.
107 * @param string The table name
108 * @param string The field name
109 * @param array The current row from which field is being rendered
110 * @param array Array of standard content for rendering form fields from TCEforms. See TCEforms for details on this. Includes for instance the value and the form field name, java script actions and more.
111 * @param array "special" configuration - what is found at position 4 in the types configuration of a field from record, parsed into an array.
112 * @param array Configuration for RTEs; A mix between TSconfig and otherwise. Contains configuration for display, which buttons are enabled, additional transformation information etc.
113 * @param string Record "type" field value.
114 * @param string Relative path for images/links in RTE; this is used when the RTE edits content from static files where the path of such media has to be transformed forth and back!
115 * @param integer PID value of record (true parent page id)
116 * @return string HTML code for RTE!
117 * @todo Define visibility
118 */
119 public function drawRTE(&$parentObject, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue) {
120 global $TSFE, $TYPO3_CONF_VARS, $TYPO3_DB;
121 $this->TCEform = $parentObject;
122 $this->client = $this->clientInfo();
123 $this->typoVersion = \TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version);
124 /* =======================================
125 * INIT THE EDITOR-SETTINGS
126 * =======================================
127 */
128 // Get the path to this extension:
129 $this->extHttpPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath($this->ID);
130 // Get the site URL
131 $this->siteURL = $GLOBALS['TSFE']->absRefPrefix ?: '';
132 // Get the host URL
133 $this->hostURL = '';
134 // Element ID + pid
135 $this->elementId = $PA['itemFormElName'];
136 $this->elementParts[0] = $table;
137 $this->elementParts[1] = $row['uid'];
138 $this->tscPID = $thePidValue;
139 $this->thePid = $thePidValue;
140 // Record "type" field value:
141 $this->typeVal = $RTEtypeVal;
142 // TCA "type" value for record
143 // RTE configuration
144 $pageTSConfig = $TSFE->getPagesTSconfig();
145 if (is_array($pageTSConfig) && is_array($pageTSConfig['RTE.'])) {
146 $this->RTEsetup = $pageTSConfig['RTE.'];
147 }
148 if (is_array($thisConfig) && !empty($thisConfig)) {
149 $this->thisConfig = $thisConfig;
150 } elseif (is_array($this->RTEsetup['default.']) && is_array($this->RTEsetup['default.']['FE.'])) {
151 $this->thisConfig = $this->RTEsetup['default.']['FE.'];
152 }
153 // Special configuration (line) and default extras:
154 $this->specConf = $specConf;
155 if ($this->thisConfig['forceHTTPS']) {
156 $this->extHttpPath = preg_replace('/^(http|https)/', 'https', $this->extHttpPath);
157 $this->siteURL = preg_replace('/^(http|https)/', 'https', $this->siteURL);
158 $this->hostURL = preg_replace('/^(http|https)/', 'https', $this->hostURL);
159 }
160 // Register RTE windows:
161 $this->TCEform->RTEwindows[] = $PA['itemFormElName'];
162 $textAreaId = preg_replace('/[^a-zA-Z0-9_:.-]/', '_', $PA['itemFormElName']);
163 $textAreaId = htmlspecialchars(preg_replace('/^[^a-zA-Z]/', 'x', $textAreaId)) . '_' . strval($this->TCEform->RTEcounter);
164 /* =======================================
165 * LANGUAGES & CHARACTER SETS
166 * =======================================
167 */
168 // Language
169 $TSFE->initLLvars();
170 $this->language = $TSFE->lang;
171 $this->LOCAL_LANG = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile('EXT:' . $this->ID . '/locallang.xml', $this->language);
172 if ($this->language == 'default' || !$this->language) {
173 $this->language = 'en';
174 }
175 $this->contentLanguageUid = max($row['sys_language_uid'], 0);
176 if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('static_info_tables')) {
177 if ($this->contentLanguageUid) {
178 $tableA = 'sys_language';
179 $tableB = 'static_languages';
180 $languagesUidsList = $this->contentLanguageUid;
181 $selectFields = $tableA . '.uid,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2,' . $tableB . '.lg_typo3';
182 $tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
183 $whereClause = $tableA . '.uid IN (' . $languagesUidsList . ') ';
184 $whereClause .= \TYPO3\CMS\Backend\Utility\BackendUtility::BEenableFields($tableA);
185 $whereClause .= \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($tableA);
186 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
187 while ($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
188 $this->contentISOLanguage = strtolower(trim($languageRow['lg_iso_2']) . (trim($languageRow['lg_country_iso_2']) ? '_' . trim($languageRow['lg_country_iso_2']) : ''));
189 $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
190 }
191 } else {
192 $this->contentISOLanguage = $GLOBALS['TSFE']->sys_language_isocode ?: 'en';
193 $selectFields = 'lg_iso_2, lg_typo3';
194 $tableAB = 'static_languages';
195 $whereClause = 'lg_iso_2 = ' . $TYPO3_DB->fullQuoteStr(strtoupper($this->contentISOLanguage), $tableAB);
196 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
197 while ($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
198 $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
199 }
200 }
201 }
202 $this->contentISOLanguage = $this->contentISOLanguage ?: ($GLOBALS['TSFE']->sys_language_isocode ?: 'en');
203 $this->contentTypo3Language = $this->contentTypo3Language ?: $GLOBALS['TSFE']->lang;
204 if ($this->contentTypo3Language == 'default') {
205 $this->contentTypo3Language = 'en';
206 }
207 // Character set
208 $this->charset = $TSFE->renderCharset;
209 $this->OutputCharset = $TSFE->metaCharset ?: $TSFE->renderCharset;
210 // Set the charset of the content
211 $this->contentCharset = $TSFE->csConvObj->charSetArray[$this->contentTypo3Language];
212 $this->contentCharset = $this->contentCharset ?: 'utf-8';
213 $this->contentCharset = trim($TSFE->config['config']['metaCharset']) ?: $this->contentCharset;
214 /* =======================================
215 * TOOLBAR CONFIGURATION
216 * =======================================
217 */
218 $this->initializeToolbarConfiguration();
219 /* =======================================
220 * SET STYLES
221 * =======================================
222 */
223 $width = 460 + ($this->TCEform->docLarge ? 150 : 0);
224 if (isset($this->thisConfig['RTEWidthOverride'])) {
225 if (strstr($this->thisConfig['RTEWidthOverride'], '%')) {
226 if ($this->client['browser'] != 'msie') {
227 $width = (int)$this->thisConfig['RTEWidthOverride'] > 0 ? $this->thisConfig['RTEWidthOverride'] : '100%';
228 }
229 } else {
230 $width = (int)$this->thisConfig['RTEWidthOverride'] > 0 ? (int)$this->thisConfig['RTEWidthOverride'] : $width;
231 }
232 }
233 $RTEWidth = strstr($width, '%') ? $width : $width . 'px';
234 $editorWrapWidth = strstr($width, '%') ? $width : ($width + 2) . 'px';
235 $height = 380;
236 $RTEHeightOverride = (int)$this->thisConfig['RTEHeightOverride'];
237 $height = $RTEHeightOverride > 0 ? $RTEHeightOverride : $height;
238 $RTEHeight = $height . 'px';
239 $editorWrapHeight = ($height + 2) . 'px';
240 $this->RTEWrapStyle = $this->RTEWrapStyle ?: ($this->RTEdivStyle ?: 'height:' . $editorWrapHeight . '; width:' . $editorWrapWidth . ';');
241 $this->RTEdivStyle = $this->RTEdivStyle ?: 'position:relative; left:0px; top:0px; height:' . $RTEHeight . '; width:' . $RTEWidth . '; border: 1px solid black;';
242 /* =======================================
243 * LOAD JS, CSS and more
244 * =======================================
245 */
246 $this->getPageRenderer();
247 // Preloading the pageStyle and including RTE skin stylesheets
248 $this->addPageStyle();
249 $this->addSkin();
250 // Register RTE in JS
251 $this->TCEform->additionalJS_post[] = $this->wrapCDATA($this->registerRTEinJS($this->TCEform->RTEcounter, '', '', '', $textAreaId));
252 // Set the save option for the RTE:
253 $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
254 // Loading ExtJs JavaScript files and inline code, if not configured in TS setup
255 if (!is_array($GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs.'])) {
256 $this->pageRenderer->loadExtJs();
257 $this->pageRenderer->enableExtJSQuickTips();
258 }
259 $this->pageRenderer->addCssFile($this->siteURL . 'typo3/js/extjs/ux/resize.css');
260 $this->pageRenderer->addJsFile($this->getFullFileName('typo3/js/extjs/ux/ext.resizable.js'));
261 $this->pageRenderer->addJsFile('sysext/backend/Resources/Public/JavaScript/notifications.js');
262 // Add RTE JavaScript
263 $this->addRteJsFiles($this->TCEform->RTEcounter);
264 $this->pageRenderer->addJsFile($this->buildJSMainLangFile($this->TCEform->RTEcounter));
265 $this->pageRenderer->addJsInlineCode('HTMLArea-init', $this->getRteInitJsCode(), TRUE);
266 /* =======================================
267 * DRAW THE EDITOR
268 * =======================================
269 */
270 // Transform value:
271 $value = $this->transformContent('rte', $PA['itemFormElValue'], $table, $field, $row, $specConf, $thisConfig, $RTErelPath, $thePidValue);
272 // Further content transformation by registered plugins
273 foreach ($this->registeredPlugins as $pluginId => $plugin) {
274 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, 'transformContent')) {
275 $value = $plugin->transformContent($value);
276 }
277 }
278 // draw the textarea
279 $item = $this->triggerField($PA['itemFormElName']) . '
280 <div id="pleasewait' . $textAreaId . '" class="pleasewait" style="display: block;" >' . $TSFE->csConvObj->conv($TSFE->getLLL('Please wait', $this->LOCAL_LANG), $this->charset, $TSFE->renderCharset) . '</div>
281 <div id="editorWrap' . $textAreaId . '" class="editorWrap" style="visibility: hidden; ' . htmlspecialchars($this->RTEWrapStyle) . '">
282 <textarea id="RTEarea' . $textAreaId . '" name="' . htmlspecialchars($PA['itemFormElName']) . '" rows="0" cols="0" style="' . htmlspecialchars($this->RTEdivStyle) . '">' . \TYPO3\CMS\Core\Utility\GeneralUtility::formatForTextarea($value) . '</textarea>
283 </div>' . LF;
284 return $item;
285 }
286
287 /**
288 * Add style sheet file to document header
289 *
290 * @param string $key: some key identifying the style sheet
291 * @param string $href: uri to the style sheet file
292 * @param string $title: value for the title attribute of the link element
293 * @param string $relation: value for the rel attribute of the link element
294 * @return void
295 */
296 protected function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet') {
297 $this->pageRenderer->addCssFile($href, $relation, 'screen', $title);
298 }
299
300 /**
301 * Return the JS-Code for copy the HTML-Code from the editor in the hidden input field.
302 * This is for submit function from the form.
303 *
304 * @param integer $RTEcounter: The index number of the RTE editing area.
305 * @param string $form: the name of the form
306 * @param string $textareaId: the id of the textarea
307 * @return string the JS-Code
308 * @todo Define visibility
309 */
310 public function setSaveRTE($RTEcounter, $form, $textareaId) {
311 return '
312 if (RTEarea[\'' . $textareaId . '\'] && !RTEarea[\'' . $textareaId . '\'].deleted) {
313 var field = document.getElementById(\'RTEarea' . $textareaId . '\');
314 if (field && field.nodeName.toLowerCase() == \'textarea\') {
315 field.value = RTEarea[\'' . $textareaId . '\'][\'editor\'].getHTML();
316 }
317 } else {
318 OK = 0;
319 }';
320 }
321
322 /**
323 * Gets instance of PageRenderer
324 *
325 * @return PageRenderer
326 */
327 public function getPageRenderer() {
328 if (!isset($this->pageRenderer)) {
329 $this->pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
330 $this->pageRenderer->setBackPath(TYPO3_mainDir);
331 }
332 return $this->pageRenderer;
333 }
334
335 /**
336 * Wrap input string in CDATA enclosure
337 *
338 * @param string $string: input to be wrapped
339 * @return string wrapped string
340 */
341 public function wrapCDATA($string) {
342 return implode(LF, array(
343 '',
344 '/*<![CDATA[*/',
345 $string,
346 '/*]]>*/'
347 ));
348 }
349 }