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