[BUGFIX] RTE: Required ExtJs css files are not loaded in frontend
[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 // Register RTE in JS
248 $this->TCEform->additionalJS_post[] = $this->wrapCDATA($this->registerRTEinJS($this->TCEform->RTEcounter, '', '', '', $textAreaId));
249 // Set the save option for the RTE:
250 $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
251 // Loading ExtJs JavaScript files and inline code, if not configured in TS setup
252 if (!is_array($GLOBALS['TSFE']->pSetup['javascriptLibs.']['ExtJs.'])) {
253 $this->pageRenderer->loadExtJs();
254 $this->pageRenderer->enableExtJSQuickTips();
255 }
256 $this->pageRenderer->addJsFile($this->getFullFileName('typo3/js/extjs/ux/ext.resizable.js'));
257 $this->pageRenderer->addJsFile('sysext/backend/Resources/Public/JavaScript/notifications.js');
258 // Preloading the pageStyle and including RTE skin stylesheets
259 $this->addPageStyle();
260 $this->pageRenderer->addCssFile($this->siteURL . 'typo3/contrib/extjs/resources/css/ext-all-notheme.css');
261 $this->pageRenderer->addCssFile($this->siteURL . 'typo3/sysext/t3skin/extjs/xtheme-t3skin.css');
262 $this->addSkin();
263 $this->pageRenderer->addCssFile($this->siteURL . 'typo3/js/extjs/ux/resize.css');
264 // Add RTE JavaScript
265 $this->addRteJsFiles($this->TCEform->RTEcounter);
266 $this->pageRenderer->addJsFile($this->buildJSMainLangFile($this->TCEform->RTEcounter));
267 $this->pageRenderer->addJsInlineCode('HTMLArea-init', $this->getRteInitJsCode(), TRUE);
268 /* =======================================
269 * DRAW THE EDITOR
270 * =======================================
271 */
272 // Transform value:
273 $value = $this->transformContent('rte', $PA['itemFormElValue'], $table, $field, $row, $specConf, $thisConfig, $RTErelPath, $thePidValue);
274 // Further content transformation by registered plugins
275 foreach ($this->registeredPlugins as $pluginId => $plugin) {
276 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, 'transformContent')) {
277 $value = $plugin->transformContent($value);
278 }
279 }
280 // draw the textarea
281 $item = $this->triggerField($PA['itemFormElName']) . '
282 <div id="pleasewait' . $textAreaId . '" class="pleasewait" style="display: block;" >' . $TSFE->csConvObj->conv($TSFE->getLLL('Please wait', $this->LOCAL_LANG), $this->charset, $TSFE->renderCharset) . '</div>
283 <div id="editorWrap' . $textAreaId . '" class="editorWrap" style="visibility: hidden; ' . htmlspecialchars($this->RTEWrapStyle) . '">
284 <textarea id="RTEarea' . $textAreaId . '" name="' . htmlspecialchars($PA['itemFormElName']) . '" rows="0" cols="0" style="' . htmlspecialchars($this->RTEdivStyle) . '">' . \TYPO3\CMS\Core\Utility\GeneralUtility::formatForTextarea($value) . '</textarea>
285 </div>' . LF;
286 return $item;
287 }
288
289 /**
290 * Add style sheet file to document header
291 *
292 * @param string $key: some key identifying the style sheet
293 * @param string $href: uri to the style sheet file
294 * @param string $title: value for the title attribute of the link element
295 * @param string $relation: value for the rel attribute of the link element
296 * @return void
297 */
298 protected function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet') {
299 $this->pageRenderer->addCssFile($href, $relation, 'screen', $title);
300 }
301
302 /**
303 * Return the JS-Code for copy the HTML-Code from the editor in the hidden input field.
304 * This is for submit function from the form.
305 *
306 * @param integer $RTEcounter: The index number of the RTE editing area.
307 * @param string $form: the name of the form
308 * @param string $textareaId: the id of the textarea
309 * @return string the JS-Code
310 * @todo Define visibility
311 */
312 public function setSaveRTE($RTEcounter, $form, $textareaId) {
313 return '
314 if (RTEarea[\'' . $textareaId . '\'] && !RTEarea[\'' . $textareaId . '\'].deleted) {
315 var field = document.getElementById(\'RTEarea' . $textareaId . '\');
316 if (field && field.nodeName.toLowerCase() == \'textarea\') {
317 field.value = RTEarea[\'' . $textareaId . '\'][\'editor\'].getHTML();
318 }
319 } else {
320 OK = 0;
321 }';
322 }
323
324 /**
325 * Gets instance of PageRenderer
326 *
327 * @return PageRenderer
328 */
329 public function getPageRenderer() {
330 if (!isset($this->pageRenderer)) {
331 $this->pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
332 $this->pageRenderer->setBackPath(TYPO3_mainDir);
333 }
334 return $this->pageRenderer;
335 }
336
337 /**
338 * Wrap input string in CDATA enclosure
339 *
340 * @param string $string: input to be wrapped
341 * @return string wrapped string
342 */
343 public function wrapCDATA($string) {
344 return implode(LF, array(
345 '',
346 '/*<![CDATA[*/',
347 $string,
348 '/*]]>*/'
349 ));
350 }
351 }