Fixed bug #14859: htmlArea RTE won't load in backend extension
[Packages/TYPO3.CMS.git] / typo3 / sysext / rtehtmlarea / class.tx_rtehtmlarea_base.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2004-2010 Kasper Skaarhoj (kasper@typo3.com)
6 * (c) 2004-2010 Philipp Borgmann <philipp.borgmann@gmx.de>
7 * (c) 2004-2010 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 textfile 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 * A RTE using the htmlArea editor
31 *
32 * @author Philipp Borgmann <philipp.borgmann@gmx.de>
33 * @author Stanislas Rolland <typo3(arobas)sjbr.ca>
34 *
35 * $Id$ *
36 */
37
38 class tx_rtehtmlarea_base extends t3lib_rteapi {
39 // Configuration of supported browsers
40 var $conf_supported_browser = array (
41 'msie' => array (
42 1 => array (
43 'version' => 6.0,
44 'system' => 'winNT'
45 ),
46 2 => array (
47 'version' => 6.0,
48 'system' => 'win98'
49 ),
50 3 => array (
51 'version' => 6.0,
52 'system' => 'win95'
53 )
54 ),
55 'gecko' => array (
56 1 => array (
57 'version' => 1.8
58 )
59 ),
60 'webkit' => array (
61 1 => array (
62 'version' => 523
63 )
64 ),
65 'opera' => array (
66 1 => array (
67 'version' => 9.62
68 )
69 )
70 );
71
72 // Always hide these toolbar buttons (TYPO3 button name)
73 var $conf_toolbar_hide = array (
74 'showhelp', // Has no content yet
75 );
76
77 // The order of the toolbar: the name is the TYPO3-button name
78 var $defaultToolbarOrder;
79
80 // Conversion array: TYPO3 button names to htmlArea button names
81 var $convertToolbarForHtmlAreaArray = array (
82 'showhelp' => 'ShowHelp',
83 'space' => 'space',
84 'bar' => 'separator',
85 'linebreak' => 'linebreak',
86 );
87
88 var $pluginButton = array();
89 var $pluginLabel = array();
90 // Alternative style for RTE <div> tag.
91 public $RTEdivStyle;
92 // Relative path to this extension. It ends with "/"
93 public $extHttpPath;
94 public $backPath = '';
95 // TYPO3 site url
96 public $siteURL;
97 // TYPO3 host url
98 public $hostURL;
99 // Typo3 version
100 public $typoVersion;
101 // Identifies the RTE as being the one from the "rtehtmlarea" extension if any external code needs to know
102 var $ID = 'rtehtmlarea';
103 // If set, the content goes into a regular TEXT area field - for developing testing of transformations.
104 var $debugMode = FALSE;
105 // For the editor
106 var $client;
107
108 /**
109 * Reference to parent object, which is an instance of the TCEforms
110 *
111 * @var t3lib_TCEforms
112 */
113 var $TCEform;
114 var $elementId;
115 var $elementParts;
116 var $tscPID;
117 var $typeVal;
118 var $thePid;
119 var $RTEsetup;
120 var $thisConfig;
121 var $confValues;
122 public $language;
123 public $contentTypo3Language;
124 public $contentISOLanguage;
125 public $contentCharset;
126 public $OutputCharset;
127 var $editorCSS;
128 var $specConf;
129 var $toolbar = array(); // Save the buttons for the toolbar
130 var $toolbarOrderArray = array();
131 protected $pluginEnabledArray = array(); // Array of plugin id's enabled in the current RTE editing area
132 protected $pluginEnabledCumulativeArray = array(); // Cumulative array of plugin id's enabled so far in any of the RTE editing areas of the form
133 protected $cumulativeScripts = array();
134 public $registeredPlugins = array(); // Array of registered plugins indexed by their plugin Id's
135 protected $fullScreen = false;
136
137 /**
138 * Returns true if the RTE is available. Here you check if the browser requirements are met.
139 * If there are reasons why the RTE cannot be displayed you simply enter them as text in ->errorLog
140 *
141 * @return boolean TRUE if this RTE object offers an RTE in the current browser environment
142 */
143
144 function isAvailable() {
145 global $TYPO3_CONF_VARS;
146
147 $this->client = $this->clientInfo();
148 $this->errorLog = array();
149 if (!$this->debugMode) { // If debug-mode, let any browser through
150 $rteIsAvailable = 0;
151 $rteConfBrowser = $this->conf_supported_browser;
152 if (is_array($rteConfBrowser)) {
153 foreach ($rteConfBrowser as $browser => $browserConf) {
154 if ($browser == $this->client['browser']) {
155 // Config for Browser found, check it:
156 if (is_array($browserConf)) {
157 foreach ($browserConf as $browserConfNr => $browserConfSub) {
158 if ($browserConfSub['version'] <= $this->client['version'] || empty($browserConfSub['version'])) {
159 // Version is correct
160 if ($browserConfSub['system'] == $this->client['system'] || empty($browserConfSub['system'])) {
161 // System is correctly
162 $rteIsAvailable = 1;
163 }// End of System
164 }// End of Version
165 }// End of foreach-BrowserSubpart
166 } else {
167 // no config for this browser found, so all versions or system with this browsers are allow
168 $rteIsAvailable = 1;
169 }
170 } // End of Browser Check
171 } // foreach: Browser Check
172 } else {
173 // no Browser config for this RTE-Editor, so all Clients are allow
174 }
175 if (!$rteIsAvailable) {
176 $this->errorLog[] = 'rte: Browser not supported. Only msie Version 5 or higher and Mozilla based client 1. and higher.';
177 }
178 if (t3lib_div::int_from_ver(TYPO3_version) < 4000000) {
179 $rteIsAvailable = 0;
180 $this->errorLog[] = 'rte: This version of htmlArea RTE cannot run under this version of TYPO3.';
181 }
182 }
183 if ($rteIsAvailable) return true;
184 }
185
186 /**
187 * Draws the RTE as an iframe
188 *
189 * @param object Reference to parent object, which is an instance of the TCEforms.
190 * @param string The table name
191 * @param string The field name
192 * @param array The current row from which field is being rendered
193 * @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.
194 * @param array "special" configuration - what is found at position 4 in the types configuration of a field from record, parsed into an array.
195 * @param array Configuration for RTEs; A mix between TSconfig and otherwise. Contains configuration for display, which buttons are enabled, additional transformation information etc.
196 * @param string Record "type" field value.
197 * @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!
198 * @param integer PID value of record (true parent page id)
199 * @return string HTML code for RTE!
200 */
201
202 function drawRTE($parentObject, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue) {
203 global $BE_USER, $LANG, $TYPO3_DB, $TYPO3_CONF_VARS;
204
205 $this->TCEform = $parentObject;
206 $inline = $this->TCEform->inline;
207 $LANG->includeLLFile('EXT:' . $this->ID . '/locallang.xml');
208 $this->client = $this->clientInfo();
209 $this->typoVersion = t3lib_div::int_from_ver(TYPO3_version);
210 $this->userUid = 'BE_' . $BE_USER->user['uid'];
211
212 // Draw form element:
213 if ($this->debugMode) { // Draws regular text area (debug mode)
214 $item = parent::drawRTE($this->TCEform, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
215 } else { // Draw real RTE
216
217 /* =======================================
218 * INIT THE EDITOR-SETTINGS
219 * =======================================
220 */
221 // Set backPath
222 $this->backPath = $this->TCEform->backPath;
223 // Get the path to this extension:
224 $this->extHttpPath = $this->backPath . t3lib_extMgm::extRelPath($this->ID);
225 // Get the site URL
226 $this->siteURL = t3lib_div::getIndpEnv('TYPO3_SITE_URL');
227 // Get the host URL
228 $this->hostURL = $this->siteURL . TYPO3_mainDir;
229 // Element ID + pid
230 $this->elementId = $PA['itemFormElName']; // Form element name
231 $this->elementParts = explode('][',preg_replace('/\]$/','',preg_replace('/^(TSFE_EDIT\[data\]\[|data\[)/','',$this->elementId)));
232 // Find the page PIDs:
233 list($this->tscPID,$this->thePid) = t3lib_BEfunc::getTSCpid(trim($this->elementParts[0]),trim($this->elementParts[1]),$thePidValue);
234
235 // Record "types" field value:
236 $this->typeVal = $RTEtypeVal; // TCA "types" value for record
237
238 // Find "thisConfig" for record/editor:
239 unset($this->RTEsetup);
240 $this->RTEsetup = $BE_USER->getTSConfig('RTE',t3lib_BEfunc::getPagesTSconfig($this->tscPID));
241 $this->thisConfig = $thisConfig;
242
243 // Special configuration and default extras:
244 $this->specConf = $specConf;
245
246 if ($this->thisConfig['forceHTTPS']) {
247 $this->extHttpPath = preg_replace('/^(http|https)/', 'https', $this->extHttpPath);
248 $this->siteURL = preg_replace('/^(http|https)/', 'https', $this->siteURL);
249 $this->hostURL = preg_replace('/^(http|https)/', 'https', $this->hostURL);
250 }
251
252 /* =======================================
253 * LANGUAGES & CHARACTER SETS
254 * =======================================
255 */
256
257 // Languages: interface and content
258 $this->language = $LANG->lang;
259 if ($this->language=='default' || !$this->language) {
260 $this->language='en';
261 }
262 $this->contentTypo3Language = $this->language;
263 $this->contentISOLanguage = 'en';
264 $this->contentLanguageUid = ($row['sys_language_uid'] > 0) ? $row['sys_language_uid'] : 0;
265 if (t3lib_extMgm::isLoaded('static_info_tables')) {
266 if ($this->contentLanguageUid) {
267 $tableA = 'sys_language';
268 $tableB = 'static_languages';
269 $languagesUidsList = $this->contentLanguageUid;
270 $selectFields = $tableA . '.uid,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2,' . $tableB . '.lg_typo3';
271 $tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
272 $whereClause = $tableA . '.uid IN (' . $languagesUidsList . ') ';
273 $whereClause .= t3lib_BEfunc::BEenableFields($tableA);
274 $whereClause .= t3lib_BEfunc::deleteClause($tableA);
275 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
276 while($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
277 $this->contentISOLanguage = strtolower(trim($languageRow['lg_iso_2']).(trim($languageRow['lg_country_iso_2'])?'_'.trim($languageRow['lg_country_iso_2']):''));
278 $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
279 }
280 } else {
281 $this->contentISOLanguage = trim($this->thisConfig['defaultContentLanguage']) ? trim($this->thisConfig['defaultContentLanguage']) : 'en';
282 $selectFields = 'lg_iso_2, lg_typo3';
283 $tableAB = 'static_languages';
284 $whereClause = 'lg_iso_2 = ' . $TYPO3_DB->fullQuoteStr(strtoupper($this->contentISOLanguage), $tableAB);
285 $res = $TYPO3_DB->exec_SELECTquery($selectFields, $tableAB, $whereClause);
286 while($languageRow = $TYPO3_DB->sql_fetch_assoc($res)) {
287 $this->contentTypo3Language = strtolower(trim($languageRow['lg_typo3']));
288 }
289 }
290 }
291
292 // Character sets: interface and content
293 $this->charset = $LANG->charSet;
294 $this->OutputCharset = $this->charset;
295
296 $this->contentCharset = $LANG->csConvObj->charSetArray[$this->contentTypo3Language];
297 $this->contentCharset = $this->contentCharset ? $this->contentCharset : 'iso-8859-1';
298 $this->origContentCharSet = $this->contentCharset;
299 $this->contentCharset = (trim($TYPO3_CONF_VARS['BE']['forceCharset']) ? trim($TYPO3_CONF_VARS['BE']['forceCharset']) : $this->contentCharset);
300
301 /* =======================================
302 * TOOLBAR CONFIGURATION
303 * =======================================
304 */
305 $this->initializeToolbarConfiguration();
306
307 /* =======================================
308 * SET STYLES
309 * =======================================
310 */
311
312 $RTEWidth = isset($BE_USER->userTS['options.']['RTESmallWidth']) ? $BE_USER->userTS['options.']['RTESmallWidth'] : '530';
313 $RTEHeight = isset($BE_USER->userTS['options.']['RTESmallHeight']) ? $BE_USER->userTS['options.']['RTESmallHeight'] : '380';
314 $RTEWidth = $RTEWidth + ($this->TCEform->docLarge ? (isset($BE_USER->userTS['options.']['RTELargeWidthIncrement']) ? $BE_USER->userTS['options.']['RTELargeWidthIncrement'] : '150') : 0);
315 $RTEWidth -= ($inline->getStructureDepth() > 0 ? ($inline->getStructureDepth()+1)*$inline->getLevelMargin() : 0);
316 if (isset($this->thisConfig['RTEWidthOverride'])) {
317 if (strstr($this->thisConfig['RTEWidthOverride'], '%')) {
318 if ($this->client['browser'] != 'msie') {
319 $RTEWidth = (intval($this->thisConfig['RTEWidthOverride']) > 0) ? $this->thisConfig['RTEWidthOverride'] : '100%';
320 }
321 } else {
322 $RTEWidth = (intval($this->thisConfig['RTEWidthOverride']) > 0) ? intval($this->thisConfig['RTEWidthOverride']) : $RTEWidth;
323 }
324 }
325 $RTEWidth = strstr($RTEWidth, '%') ? $RTEWidth : $RTEWidth . 'px';
326 $RTEHeight = $RTEHeight + ($this->TCEform->docLarge ? (isset($BE_USER->userTS['options.']['RTELargeHeightIncrement']) ? $BE_USER->userTS['options.']['RTELargeHeightIncrement'] : 0) : 0);
327 $RTEHeightOverride = intval($this->thisConfig['RTEHeightOverride']);
328 $RTEHeight = ($RTEHeightOverride > 0) ? $RTEHeightOverride : $RTEHeight;
329 $editorWrapWidth = '99%';
330 $editorWrapHeight = '100%';
331 $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:'.$RTEWidth.'; border: 1px solid black; padding: 2px 2px 2px 2px;';
332
333 /* =======================================
334 * LOAD CSS AND JAVASCRIPT
335 * =======================================
336 */
337 // Preloading the pageStyle and including RTE skin stylesheets
338 $this->addPageStyle();
339 $this->addSkin();
340 // Loading JavaScript files and code
341 if ($this->TCEform->RTEcounter == 1) {
342 $this->TCEform->additionalJS_pre['rtehtmlarea-loadJScode'] = $this->loadJScode($this->TCEform->RTEcounter);
343 }
344 $this->TCEform->additionalCode_pre['rtehtmlarea-loadJSfiles'] = $this->loadJSfiles($this->TCEform->RTEcounter);
345 $pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
346 $pageRenderer->enableExtJSQuickTips();
347 if (!$GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts']) {
348 $pageRenderer->enableExtJsDebug();
349 }
350 /* =======================================
351 * DRAW THE EDITOR
352 * =======================================
353 */
354
355 // Transform value:
356 $value = $this->transformContent('rte',$PA['itemFormElValue'],$table,$field,$row,$specConf,$thisConfig,$RTErelPath,$thePidValue);
357
358 // Further content transformation by registered plugins
359 foreach ($this->registeredPlugins as $pluginId => $plugin) {
360 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, "transformContent")) {
361 $value = $plugin->transformContent($value);
362 }
363 }
364 // Register RTE windows
365 $this->TCEform->RTEwindows[] = $PA['itemFormElName'];
366 $textAreaId = htmlspecialchars($PA['itemFormElName']);
367
368 // Check if wizard_rte called this for fullscreen edtition; if so, change the size of the RTE to fullscreen using JS
369 if (basename(PATH_thisScript) == 'wizard_rte.php') {
370 $this->fullScreen = true;
371 $editorWrapWidth = '100%';
372 $editorWrapHeight = '100%';
373 $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:100%; width:100%; border: 1px solid black; padding: 2px 0px 2px 2px;';
374 }
375
376 // Register RTE in JS:
377 $this->TCEform->additionalJS_post[] = $this->registerRTEinJS($this->TCEform->RTEcounter, $table, $row['uid'], $field, $textAreaId);
378
379 // Set the save option for the RTE:
380 $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
381 $this->TCEform->additionalJS_delete[] = $this->setDeleteRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
382
383 // Draw the textarea
384 $visibility = 'hidden';
385 $item = $this->triggerField($PA['itemFormElName']).'
386 <div id="pleasewait' . $textAreaId . '" class="pleasewait" style="display: block;" >' . $LANG->getLL('Please wait') . '</div>
387 <div id="editorWrap' . $textAreaId . '" class="editorWrap" style="visibility: hidden; width:' . $editorWrapWidth . '; height:' . $editorWrapHeight . ';">
388 <textarea id="RTEarea' . $textAreaId . '" name="'.htmlspecialchars($PA['itemFormElName']).'" style="'.t3lib_div::deHSCentities(htmlspecialchars($this->RTEdivStyle)).'">'.t3lib_div::formatForTextarea($value).'</textarea>
389 </div>' . ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableDebugMode'] ? '<div id="HTMLAreaLog"></div>' : '') . '
390 ';
391 }
392
393 // Return form item:
394 return $item;
395 }
396
397 /**
398 * Add link to content style sheet to document header
399 *
400 * @return void
401 */
402 protected function addPageStyle() {
403 // Get stylesheet file name from Page TSConfig if any
404 $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
405 $this->addStyleSheet(
406 'rtehtmlarea-page-style',
407 $this->getFullFileName($filename),
408 'htmlArea RTE Content CSS',
409 'alternate stylesheet'
410 );
411 }
412
413 /**
414 * Add links to skin style sheet(s) to document header
415 *
416 * @return void
417 */
418 protected function addSkin() {
419 // Get skin file name from Page TSConfig if any
420 $skinFilename = trim($this->thisConfig['skin']) ? trim($this->thisConfig['skin']) : 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
421 $this->editorCSS = $this->getFullFileName($skinFilename);
422 $skinDir = dirname($this->editorCSS);
423 // Editing area style sheet
424 $this->editedContentCSS = $skinDir . '/htmlarea-edited-content.css';
425 $this->addStyleSheet(
426 'rtehtmlarea-editing-area-skin',
427 $this->editedContentCSS
428 );
429 // Main skin
430 $this->addStyleSheet(
431 'rtehtmlarea-skin',
432 $this->editorCSS
433 );
434 // Additional icons from registered plugins
435 foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
436 if (is_object($this->registeredPlugins[$pluginId])) {
437 $pathToSkin = $this->registeredPlugins[$pluginId]->getPathToSkin();
438 if ($pathToSkin) {
439 $key = $this->registeredPlugins[$pluginId]->getExtensionKey();
440 $this->addStyleSheet(
441 'rtehtmlarea-plugin-' . $pluginId . '-skin',
442 ($this->is_FE() ? t3lib_extMgm::siteRelPath($key) : $this->backPath . t3lib_extMgm::extRelPath($key)) . $pathToSkin
443 );
444 }
445 }
446 }
447 }
448
449 /**
450 * Add style sheet file to document header
451 *
452 * @param string $key: some key identifying the style sheet
453 * @param string $href: uri to the style sheet file
454 * @param string $title: value for the title attribute of the link element
455 * @return string $relation: value for the rel attribute of the link element
456 * @return void
457 */
458 protected function addStyleSheet($key, $href, $title='', $relation='stylesheet') {
459 // If it was not known that an RTE-enabled would be created when the page was first created, the css would not be added to head
460 if (is_object($this->TCEform->inline) && $this->TCEform->inline->isAjaxCall) {
461 $this->TCEform->additionalCode_pre[$key] = '<link rel="' . $relation . '" type="text/css" href="' . $href . '" title="' . $title. '" />';
462 } else {
463 $pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
464 $pageRenderer->addCssFile($href, $relation, 'screen', $title);
465 }
466 }
467
468 /**
469 * Initialize toolbar configuration and enable registered plugins
470 *
471 * @return void
472 */
473 protected function initializeToolbarConfiguration() {
474
475 // Enable registred plugins
476 $this->enableRegisteredPlugins();
477
478 // Configure toolbar
479 $this->setToolbar();
480
481 // Check if some plugins need to be disabled
482 $this->setPlugins();
483
484 // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
485 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = $this->pluginEnabledArray;
486 if ($this->TCEform->RTEcounter > 1 && isset($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1]) && is_array($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])) {
487 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = array_unique(array_values(array_merge($this->pluginEnabledArray,$this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])));
488 }
489 }
490
491 /**
492 * Add registered plugins to the array of enabled plugins
493 *
494 */
495 function enableRegisteredPlugins() {
496 global $TYPO3_CONF_VARS;
497 // Traverse registered plugins
498 if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'])) {
499 foreach($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'] as $pluginId => $pluginObjectConfiguration) {
500 $plugin = false;
501 if (is_array($pluginObjectConfiguration) && count($pluginObjectConfiguration)) {
502 $plugin = t3lib_div::getUserObj($pluginObjectConfiguration['objectReference']);
503 }
504 if (is_object($plugin)) {
505 if ($plugin->main($this)) {
506 $this->registeredPlugins[$pluginId] = $plugin;
507 // Override buttons from previously registered plugins
508 $pluginButtons = t3lib_div::trimExplode(',', $plugin->getPluginButtons(), 1);
509 foreach ($this->pluginButton as $previousPluginId => $buttonList) {
510 $this->pluginButton[$previousPluginId] = implode(',',array_diff(t3lib_div::trimExplode(',', $this->pluginButton[$previousPluginId], 1), $pluginButtons));
511 }
512 $this->pluginButton[$pluginId] = $plugin->getPluginButtons();
513 $pluginLabels = t3lib_div::trimExplode(',', $plugin->getPluginLabels(), 1);
514 foreach ($this->pluginLabel as $previousPluginId => $labelList) {
515 $this->pluginLabel[$previousPluginId] = implode(',',array_diff(t3lib_div::trimExplode(',', $this->pluginLabel[$previousPluginId], 1), $pluginLabels));
516 }
517 $this->pluginLabel[$pluginId] = $plugin->getPluginLabels();
518 $this->pluginEnabledArray[] = $pluginId;
519 }
520 }
521 }
522 }
523 // Process overrides
524 $hidePlugins = array();
525 foreach ($this->registeredPlugins as $pluginId => $plugin) {
526 if ($plugin->addsButtons() && !$this->pluginButton[$pluginId]) {
527 $hidePlugins[] = $pluginId;
528 }
529 }
530 $this->pluginEnabledArray = array_unique(array_diff($this->pluginEnabledArray, $hidePlugins));
531 }
532
533 /**
534 * Set the toolbar config (only in this PHP-Object, not in JS):
535 *
536 */
537
538 function setToolbar() {
539 global $BE_USER;
540
541 if ($this->client['browser'] == 'msie' || $this->client['browser'] == 'opera') {
542 $this->thisConfig['keepButtonGroupTogether'] = 0;
543 }
544
545 $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
546 bar, formattext, bold, strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
547 bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, line,
548 bar, left, center, right, justifyfull,
549 bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, lefttoright, righttoleft, language, showlanguagemarks,
550 bar, textcolor, bgcolor, textindicator,
551 bar, emoticon, insertcharacter, link, unlink, image, table,' . (($this->thisConfig['hideTableOperationsInToolbar'] && is_array($this->thisConfig['buttons.']) && is_array($this->thisConfig['buttons.']['toggleborders.']) && $this->thisConfig['buttons.']['toggleborders.']['keepInToolbar']) ? ' toggleborders,': '') . ' user, acronym, bar, findreplace, spellcheck,
552 bar, chMode, inserttag, removeformat, bar, copy, cut, paste, bar, undo, redo, bar, showhelp, about, linebreak,
553 ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
554 columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
555 cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
556
557 // Additional buttons from registered plugins
558 foreach($this->registeredPlugins as $pluginId => $plugin) {
559 if ($this->isPluginEnabled($pluginId)) {
560 $this->defaultToolbarOrder = $plugin->addButtonsToToolbar();
561 }
562 }
563 $toolbarOrder = $this->thisConfig['toolbarOrder'] ? $this->thisConfig['toolbarOrder'] : $this->defaultToolbarOrder;
564
565 // Getting rid of undefined buttons
566 $this->toolbarOrderArray = array_intersect(t3lib_div::trimExplode(',', $toolbarOrder, 1), t3lib_div::trimExplode(',', $this->defaultToolbarOrder, 1));
567 $toolbarOrder = array_unique(array_values($this->toolbarOrderArray));
568
569 // Fetching specConf for field from backend
570 $pList = is_array($this->specConf['richtext']['parameters']) ? implode(',',$this->specConf['richtext']['parameters']) : '';
571 if ($pList != '*') { // If not all
572 $show = is_array($this->specConf['richtext']['parameters']) ? $this->specConf['richtext']['parameters'] : array();
573 if ($this->thisConfig['showButtons']) {
574 if (!t3lib_div::inList($this->thisConfig['showButtons'],'*')) {
575 $show = array_unique(array_merge($show,t3lib_div::trimExplode(',',$this->thisConfig['showButtons'],1)));
576 } else {
577 $show = array_unique(array_merge($show, $toolbarOrder));
578 }
579 }
580 if (is_array($this->thisConfig['showButtons.'])) {
581 foreach ($this->thisConfig['showButtons.'] as $buttonId => $value) {
582 if ($value) $show[] = $buttonId;
583 }
584 $show = array_unique($show);
585 }
586 } else {
587 $show = $toolbarOrder;
588 }
589
590 // Resticting to RTEkeyList for backend user
591 if(is_object($BE_USER)) {
592 $RTEkeyList = isset($BE_USER->userTS['options.']['RTEkeyList']) ? $BE_USER->userTS['options.']['RTEkeyList'] : '*';
593 if ($RTEkeyList != '*') { // If not all
594 $show = array_intersect($show, t3lib_div::trimExplode(',',$RTEkeyList,1));
595 }
596 }
597
598 // Hiding buttons of disabled plugins
599 $hideButtons = array('space', 'bar', 'linebreak');
600 foreach ($this->pluginButton as $pluginId => $buttonList) {
601 if (!$this->isPluginEnabled($pluginId)) {
602 $buttonArray = t3lib_div::trimExplode(',',$buttonList,1);
603 foreach ($buttonArray as $button) {
604 $hideButtons[] = $button;
605 }
606 }
607 }
608
609 // Hiding labels of disabled plugins
610 foreach ($this->pluginLabel as $pluginId => $label) {
611 if (!$this->isPluginEnabled($pluginId)) {
612 $hideButtons[] = $label;
613 }
614 }
615
616 // Hiding buttons
617 $show = array_diff($show, $this->conf_toolbar_hide, t3lib_div::trimExplode(',',$this->thisConfig['hideButtons'],1));
618
619 // Apply toolbar constraints from registered plugins
620 foreach ($this->registeredPlugins as $pluginId => $plugin) {
621 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, "applyToolbarConstraints")) {
622 $show = $plugin->applyToolbarConstraints($show);
623 }
624 }
625 // Getting rid of the buttons for which we have no position
626 $show = array_intersect($show, $toolbarOrder);
627 $this->toolbar = $show;
628 }
629
630 /**
631 * Disable some plugins
632 *
633 */
634 function setPlugins() {
635
636 // Disabling a plugin that adds buttons if none of its buttons is in the toolbar
637 $hidePlugins = array();
638 foreach ($this->pluginButton as $pluginId => $buttonList) {
639 if ($this->registeredPlugins[$pluginId]->addsButtons()) {
640 $showPlugin = false;
641 $buttonArray = t3lib_div::trimExplode(',', $buttonList, 1);
642 foreach ($buttonArray as $button) {
643 if (in_array($button, $this->toolbar)) {
644 $showPlugin = true;
645 }
646 }
647 if (!$showPlugin) {
648 $hidePlugins[] = $pluginId;
649 }
650 }
651 }
652 $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
653
654 // Hiding labels of disabled plugins
655 $hideLabels = array();
656 foreach ($this->pluginLabel as $pluginId => $label) {
657 if (!$this->isPluginEnabled($pluginId)) {
658 $hideLabels[] = $label;
659 }
660 }
661 $this->toolbar = array_diff($this->toolbar, $hideLabels);
662
663 // Adding plugins declared as prerequisites by enabled plugins
664 $requiredPlugins = array();
665 foreach ($this->registeredPlugins as $pluginId => $plugin) {
666 if ($this->isPluginEnabled($pluginId)) {
667 $requiredPlugins = array_merge($requiredPlugins, t3lib_div::trimExplode(',', $plugin->getRequiredPlugins(), 1));
668 }
669 }
670 $requiredPlugins = array_unique($requiredPlugins);
671 foreach ($requiredPlugins as $pluginId) {
672 if (is_object($this->registeredPlugins[$pluginId]) && !$this->isPluginEnabled($pluginId)) {
673 $this->pluginEnabledArray[] = $pluginId;
674 }
675 }
676 $this->pluginEnabledArray = array_unique($this->pluginEnabledArray);
677
678 // Completing the toolbar conversion array for htmlArea
679 foreach ($this->registeredPlugins as $pluginId => $plugin) {
680 if ($this->isPluginEnabled($pluginId)) {
681 $this->convertToolbarForHtmlAreaArray = array_unique(array_merge($this->convertToolbarForHtmlAreaArray, $plugin->getConvertToolbarForHtmlAreaArray()));
682 }
683 }
684 }
685
686 /**
687 * Convert the TYPO3 names of buttons into the names for htmlArea RTE
688 *
689 * @param string buttonname (typo3-name)
690 * @return string buttonname (htmlarea-name)
691 */
692
693 function convertToolbarForHTMLArea($button) {
694 return $this->convertToolbarForHtmlAreaArray[$button];
695 }
696 /**
697 * Return the HTML code for loading the Javascript files
698 *
699 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
700 *
701 * @return string the html code for loading the Javascript Files
702 */
703 function loadJSfiles($RTEcounter) {
704 // Re-initialize the scripts array so that only the cumulative set of plugins of the last RTE on the page is used
705 $this->cumulativeScripts[$RTEcounter] = array();
706 $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea.js', 'htmlarea', 'js', '', TRUE);
707 if ($this->client['browser'] == 'msie') {
708 $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-ie.js', 'htmlarea-ie', 'js', '', TRUE);
709 } else {
710 $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-gecko.js', 'htmlarea-gecko', 'js', '', TRUE);
711 }
712 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
713 $extensionKey = is_object($this->registeredPlugins[$pluginId]) ? $this->registeredPlugins[$pluginId]->getExtensionKey() : $this->ID;
714 $this->writeTemporaryFile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $pluginId . '/' . strtolower(preg_replace('/([a-z])([A-Z])([a-z])/', "$1".'-'."$2"."$3", $pluginId)) . '.js', $pluginId, 'js', '', TRUE);
715 }
716 $this->buildJSMainLangFile($RTEcounter);
717 // Avoid re-initialization on AJax call when RTEarea object was already initialized
718 $loadJavascriptCode = '
719 <script type="text/javascript" src="' . $this->doConcatenate($RTEcounter) . '"></script>
720 <script type="text/javascript">
721 /*<![CDATA[*/
722 if (typeof(RTEarea) == "undefined") {
723 RTEarea = new Object();
724 RTEarea[0] = new Object();
725 RTEarea[0].version = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['version'] . '";
726 RTEarea[0].editorUrl = "' . $this->extHttpPath . 'htmlarea/";
727 RTEarea[0].editorCSS = "' . t3lib_div::createVersionNumberedFilename($this->editorCSS) . '";
728 RTEarea[0].editorSkin = "' . dirname($this->editorCSS) . '/";
729 RTEarea[0].editedContentCSS = "' . t3lib_div::createVersionNumberedFilename($this->editedContentCSS) . '";
730 RTEarea[0].hostUrl = "' . $this->hostURL . '";
731 RTEarea[0].enableDebugMode = ' . ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableDebugMode'] ? 'true' : 'false') . ';
732 RTEarea.init = function() {
733 if (typeof(HTMLArea) == "undefined" || !Ext.isReady) {
734 window.setTimeout("RTEarea.init();", 40);
735 } else {
736 Ext.QuickTips.init();
737 HTMLArea.init();
738 }
739 };
740 RTEarea.initEditor = function(editorNumber) {
741 if (typeof(HTMLArea) == "undefined") {
742 RTEarea.initEditor.defer(40, null, [editorNumber]);
743 } else {
744 HTMLArea.initEditor(editorNumber);
745 }
746 };
747 }
748 /*]]>*/
749 </script>';
750 return $loadJavascriptCode;
751 }
752
753 /**
754 * Return the Javascript code for initializing the RTE
755 *
756 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
757 *
758 * @return string the Javascript code for initializing the RTE
759 */
760 function loadJScode($RTEcounter) {
761 return (!$this->is_FE() ? '' : '
762 ' . '/*<![CDATA[*/') . '
763 RTEarea.init();' . (!$this->is_FE() ? '' : '
764 /*]]>*/
765 ');
766 }
767
768 /**
769 * Return the Javascript code for configuring the RTE
770 *
771 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
772 * @param string $table: The table that includes this RTE (optional, necessary for IRRE).
773 * @param string $uid: The uid of that table that includes this RTE (optional, necessary for IRRE).
774 * @param string $field: The field of that record that includes this RTE (optional).
775 *
776 * @return string the Javascript code for configuring the RTE
777 */
778 function registerRTEinJS($RTEcounter, $table='', $uid='', $field='', $textAreaId = '') {
779
780 $configureRTEInJavascriptString = (!$this->is_FE() ? '' : '
781 ' . '/*<![CDATA[*/') . '
782 if (typeof(configureEditorInstance) == "undefined") {
783 configureEditorInstance = new Object();
784 }
785 configureEditorInstance["' . $textAreaId . '"] = function() {
786 if (typeof(RTEarea) == "undefined" || typeof(HTMLArea) == "undefined") {
787 window.setTimeout("configureEditorInstance[\'' . $textAreaId . '\']();", 40);
788 } else {
789 editornumber = "' . $textAreaId . '";
790 RTEarea[editornumber] = new Object();
791 RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";
792 RTEarea[editornumber].number = editornumber;
793 RTEarea[editornumber].deleted = false;
794 RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
795 RTEarea[editornumber].id = "RTEarea" + editornumber;
796 RTEarea[editornumber].RTEWidthOverride = "' . trim($this->thisConfig['RTEWidthOverride']) . '";
797 RTEarea[editornumber].RTEHeightOverride = "' . trim($this->thisConfig['RTEHeightOverride']) . '";
798 RTEarea[editornumber].fullScreen = ' . ($this->fullScreen ? 'true' : 'false') . ';
799 RTEarea[editornumber].showStatusBar = ' . (trim($this->thisConfig['showStatusBar'])?'true':'false') . ';
800 RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean'])?'true':'false') . ';
801 RTEarea[editornumber].htmlRemoveComments = ' . (trim($this->thisConfig['removeComments'])?'true':'false') . ';
802 RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs'])?'true':'false') . ';
803 RTEarea[editornumber].disableObjectResizing = ' . (trim($this->thisConfig['disableObjectResizing'])?'true':'false') . ';
804 RTEarea[editornumber].removeTrailingBR = ' . (trim($this->thisConfig['removeTrailingBR'])?'true':'false') . ';
805 RTEarea[editornumber].useCSS = ' . (trim($this->thisConfig['useCSS'])?'true':'false') . ';
806 RTEarea[editornumber].keepButtonGroupTogether = ' . (trim($this->thisConfig['keepButtonGroupTogether'])?'true':'false') . ';
807 RTEarea[editornumber].disablePCexamples = ' . (trim($this->thisConfig['disablePCexamples'])?'true':'false') . ';
808 RTEarea[editornumber].showTagFreeClasses = ' . (trim($this->thisConfig['showTagFreeClasses'])?'true':'false') . ';
809 RTEarea[editornumber].useHTTPS = ' . ((trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'])?'true':'false') . ';
810 RTEarea[editornumber].tceformsNested = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(true) : '[]') . ';
811 RTEarea[editornumber].dialogueWindows = new Object();
812 RTEarea[editornumber].dialogueWindows.defaultPositionFromTop = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop'])? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) : '100') . ';
813 RTEarea[editornumber].dialogueWindows.defaultPositionFromLeft = ' . (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'])? intval($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) : '100') . ';
814 RTEarea[editornumber].dialogueWindows.doNotResize = ' . (trim($this->thisConfig['dialogueWindows.']['doNotResize'])?'true':'false') . ';
815 RTEarea[editornumber].dialogueWindows.doNotCenter = ' . (trim($this->thisConfig['dialogueWindows.']['doNotCenter'])?'true':'false') . ';';
816
817 // The following properties apply only to the backend
818 if (!$this->is_FE()) {
819 $configureRTEInJavascriptString .= '
820 RTEarea[editornumber].sys_language_content = "' . $this->contentLanguageUid . '";
821 RTEarea[editornumber].typo3ContentLanguage = "' . $this->contentTypo3Language . '";
822 RTEarea[editornumber].typo3ContentCharset = "' . $this->contentCharset . '";
823 RTEarea[editornumber].userUid = "' . $this->userUid . '";';
824 }
825
826 // Setting the plugin flags
827 $configureRTEInJavascriptString .= '
828 RTEarea[editornumber].plugin = new Object();
829 RTEarea[editornumber].pathToPluginDirectory = new Object();';
830 foreach ($this->pluginEnabledArray as $pluginId) {
831 $configureRTEInJavascriptString .= '
832 RTEarea[editornumber].plugin.'.$pluginId.' = true;';
833 if (is_object($this->registeredPlugins[$pluginId])) {
834 $pathToPluginDirectory = $this->registeredPlugins[$pluginId]->getPathToPluginDirectory();
835 if ($pathToPluginDirectory) {
836 $configureRTEInJavascriptString .= '
837 RTEarea[editornumber].pathToPluginDirectory.'.$pluginId.' = "' . $pathToPluginDirectory . '";';
838 }
839 }
840 }
841
842 // Setting the buttons configuration
843 $configureRTEInJavascriptString .= '
844 RTEarea[editornumber].buttons = new Object();';
845 if (is_array($this->thisConfig['buttons.'])) {
846 foreach ($this->thisConfig['buttons.'] as $buttonIndex => $conf) {
847 $button = substr($buttonIndex, 0, -1);
848 if (in_array($button,$this->toolbar)) {
849 $configureRTEInJavascriptString .= '
850 RTEarea[editornumber].buttons.'.$button.' = ' . $this->buildNestedJSArray($conf) . ';';
851 }
852 }
853 }
854
855 // Setting the list of tags to be removed if specified in the RTE config
856 if (trim($this->thisConfig['removeTags'])) {
857 $configureRTEInJavascriptString .= '
858 RTEarea[editornumber].htmlRemoveTags = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTags'], 1)) . ')$/i;';
859 }
860
861 // Setting the list of tags to be removed with their contents if specified in the RTE config
862 if (trim($this->thisConfig['removeTagsAndContents'])) {
863 $configureRTEInJavascriptString .= '
864 RTEarea[editornumber].htmlRemoveTagsAndContents = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTagsAndContents'], 1)) . ')$/i;';
865 }
866 // Process default style configuration
867 $configureRTEInJavascriptString .= '
868 RTEarea[editornumber].defaultPageStyle = "' . $this->writeTemporaryFile('', 'defaultPageStyle', 'css', $this->buildStyleSheet()) . '";';
869 // Setting the pageStyle
870 $filename = trim($this->thisConfig['contentCSS']) ? trim($this->thisConfig['contentCSS']) : 'EXT:' . $this->ID . '/res/contentcss/default.css';
871 $configureRTEInJavascriptString .= '
872 RTEarea[editornumber].pageStyle = "' . t3lib_div::createVersionNumberedFilename($this->getFullFileName($filename)) .'";';
873 // Process classes configuration
874 $classesConfigurationRequired = false;
875 foreach ($this->registeredPlugins as $pluginId => $plugin) {
876 if ($this->isPluginEnabled($pluginId)) {
877 $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
878 }
879 }
880 if ($classesConfigurationRequired) {
881 $configureRTEInJavascriptString .= $this->buildJSClassesConfig($RTEcounter);
882 }
883 // Add Javascript configuration for registered plugins
884 foreach ($this->registeredPlugins as $pluginId => $plugin) {
885 if ($this->isPluginEnabled($pluginId)) {
886 $configureRTEInJavascriptString .= $plugin->buildJavascriptConfiguration('editornumber');
887 }
888 }
889 // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
890 $configureRTEInJavascriptString .= '
891 RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';
892 RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';
893 RTEarea.initEditor(editornumber);
894 }
895 };
896 configureEditorInstance["' . $textAreaId . '"]();'. (!$this->is_FE() ? '' : '
897 /*]]>*/');
898 return $configureRTEInJavascriptString;
899 }
900
901 /**
902 * Return true, if the plugin can be loaded
903 *
904 * @param string $pluginId: The identification string of the plugin
905 *
906 * @return boolean true if the plugin can be loaded
907 */
908
909 function isPluginEnabled($pluginId) {
910 return in_array($pluginId, $this->pluginEnabledArray);
911 }
912
913 /**
914 * Build the default content style sheet
915 *
916 * @return string Style sheet
917 */
918 function buildStyleSheet() {
919
920 if (!trim($this->thisConfig['ignoreMainStyleOverride'])) {
921 $mainStyle_font = $this->thisConfig['mainStyle_font'] ? $this->thisConfig['mainStyle_font']: 'Verdana,sans-serif';
922
923 $mainElements = array();
924 $mainElements['P'] = $this->thisConfig['mainStyleOverride_add.']['P'];
925 $elList = explode(',','H1,H2,H3,H4,H5,H6,PRE');
926 foreach ($elList as $elListName) {
927 if ($this->thisConfig['mainStyleOverride_add.'][$elListName]) {
928 $mainElements[$elListName] = $this->thisConfig['mainStyleOverride_add.'][$elListName];
929 }
930 }
931
932 $addElementCode = '';
933 foreach ($mainElements as $elListName => $elValue) {
934 $addElementCode .= strToLower($elListName) . ' {' . $elValue . '}' . LF;
935 }
936
937 $stylesheet = $this->thisConfig['mainStyleOverride'] ? $this->thisConfig['mainStyleOverride'] : LF .
938 'body.htmlarea-content-body { font-family: ' . $mainStyle_font .
939 '; font-size: '.($this->thisConfig['mainStyle_size'] ? $this->thisConfig['mainStyle_size'] : '12px') .
940 '; color: '.($this->thisConfig['mainStyle_color']?$this->thisConfig['mainStyle_color'] : 'black') .
941 '; background-color: '.($this->thisConfig['mainStyle_bgcolor'] ? $this->thisConfig['mainStyle_bgcolor'] : 'white') .
942 ';'.$this->thisConfig['mainStyleOverride_add.']['BODY'].'}' . LF .
943 'td { ' . $this->thisConfig['mainStyleOverride_add.']['TD'].'}' . LF .
944 'div { ' . $this->thisConfig['mainStyleOverride_add.']['DIV'].'}' . LF .
945 'pre { ' . $this->thisConfig['mainStyleOverride_add.']['PRE'].'}' . LF .
946 'ol { ' . $this->thisConfig['mainStyleOverride_add.']['OL'].'}' . LF .
947 'ul { ' . $this->thisConfig['mainStyleOverride_add.']['UL'].'}' . LF .
948 'blockquote { ' . $this->thisConfig['mainStyleOverride_add.']['BLOCKQUOTE'].'}' . LF .
949 $addElementCode;
950
951 if (is_array($this->thisConfig['inlineStyle.'])) {
952 $stylesheet .= LF . implode(LF, $this->thisConfig['inlineStyle.']) . LF;
953 }
954 } else {
955 $stylesheet = '/* mainStyleOverride and inlineStyle properties ignored. */';
956 }
957 return $stylesheet;
958 }
959
960 /**
961 * Return Javascript configuration of classes
962 *
963 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
964 *
965 * @return string Javascript configuration of classes
966 */
967 function buildJSClassesConfig($RTEcounter) {
968 // Build JS array of lists of classes
969 $classesTagList = 'classesCharacter, classesParagraph, classesImage, classesTable, classesLinks, classesTD';
970 $classesTagConvert = array( 'classesCharacter' => 'span', 'classesParagraph' => 'div', 'classesImage' => 'img', 'classesTable' => 'table', 'classesLinks' => 'a', 'classesTD' => 'td');
971 $classesTagArray = t3lib_div::trimExplode(',' , $classesTagList);
972 $configureRTEInJavascriptString = '
973 RTEarea[editornumber].classesTag = new Object();';
974 foreach ($classesTagArray as $classesTagName) {
975 $HTMLAreaJSClasses = ($this->thisConfig[$classesTagName])?('"' . $this->cleanList($this->thisConfig[$classesTagName]) . '";'):'null;';
976 $configureRTEInJavascriptString .= '
977 RTEarea[editornumber].classesTag.'. $classesTagConvert[$classesTagName] .' = '. $HTMLAreaJSClasses;
978 }
979 // Include JS arrays of configured classes
980 $configureRTEInJavascriptString .= '
981 RTEarea[editornumber].classesUrl = "' . $this->writeTemporaryFile('', 'classes_'.$LANG->lang, 'js', $this->buildJSClassesArray()) . '";';
982 return $configureRTEInJavascriptString;
983 }
984
985 /**
986 * Return JS arrays of classes configuration
987 *
988 * @return string JS classes arrays
989 */
990 function buildJSClassesArray() {
991 if ($this->is_FE()) {
992 $RTEProperties = $this->RTEsetup;
993 } else {
994 $RTEProperties = $this->RTEsetup['properties'];
995 }
996 $classesArray = array('labels' => array(), 'values' => array(), 'noShow' => array(), 'alternating' => array(), 'counting' => array(), 'XOR' => array());
997 $JSClassesArray = '';
998 // Scanning the list of classes if specified in the RTE config
999 if (is_array($RTEProperties['classes.'])) {
1000 foreach ($RTEProperties['classes.'] as $className => $conf) {
1001 $className = rtrim($className, '.');
1002 $classesArray['labels'][$className] = $this->getPageConfigLabel($conf['name'], FALSE);
1003 $classesArray['values'][$className] = str_replace('\\\'', '\'', $conf['value']);
1004 if (isset($conf['noShow'])) {
1005 $classesArray['noShow'][$className] = $conf['noShow'];
1006 }
1007 if (is_array($conf['alternating.'])) {
1008 $classesArray['alternating'][$className] = $conf['alternating.'];
1009 }
1010 if (is_array($conf['counting.'])) {
1011 $classesArray['counting'][$className] = $conf['counting.'];
1012 }
1013 }
1014 }
1015 // Scanning the list of sets of mutually exclusives classes if specified in the RTE config
1016 if (is_array($RTEProperties['mutuallyExclusiveClasses.'])) {
1017 foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
1018 $classSet = t3lib_div::trimExplode(',', $conf, 1);
1019 $classList = implode(',', $classSet);
1020 foreach ($classSet as $className) {
1021 $classesArray['XOR'][$className] = '/^(' . implode('|', t3lib_div::trimExplode(',', t3lib_div::rmFromList($className, $classList), 1)) . ')$/';
1022 }
1023 }
1024 }
1025 foreach ($classesArray as $key => $subArray) {
1026 $JSClassesArray .= 'HTMLArea.classes' . ucfirst($key) . ' = ' . $this->buildNestedJSArray($subArray) . ';' . LF;
1027 }
1028 return $JSClassesArray;
1029 }
1030
1031 /**
1032 * Translate Page TS Config array in JS nested array definition
1033 * Replace 0 values with false
1034 * Unquote regular expression values
1035 * Replace empty arrays with empty objects
1036 *
1037 * @param array $conf: Page TSConfig configuration array
1038 *
1039 * @return string nested JS array definition
1040 */
1041 function buildNestedJSArray($conf) {
1042 $convertedConf = t3lib_div::removeDotsFromTS($conf);
1043 if ($this->is_FE()) {
1044 $GLOBALS['TSFE']->csConvObj->convArray($convertedConf, ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] ? $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] : 'iso-8859-1'), 'utf-8');
1045 } else {
1046 $GLOBALS['LANG']->csConvObj->convArray($convertedConf, $GLOBALS['LANG']->charSet, 'utf-8');
1047 }
1048 return str_replace(array(':"0"', ':"\/^(', ')$\/i"', ':"\/^(', ')$\/"', '[]'), array(':false', ':/^(', ')$/i', ':/^(', ')$/', '{}'), json_encode($convertedConf));
1049 }
1050
1051 /**
1052 * Return a Javascript localization array for htmlArea RTE
1053 *
1054 * @return string Javascript localization array
1055 */
1056 function buildJSMainLangArray() {
1057 $JSLanguageArray = 'HTMLArea.I18N = new Object();' . LF;
1058 $labelsArray = array('tooltips' => array(), 'msg' => array(), 'dialogs' => array());
1059 foreach ($labelsArray as $labels => $subArray) {
1060 $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $this->ID . '/htmlarea/locallang_' . $labels . '.xml', $this->language, 'utf-8');
1061 if (!empty($LOCAL_LANG[$this->language])) {
1062 $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language]);
1063 } else {
1064 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1065 }
1066 $labelsArray[$labels] = $LOCAL_LANG[$this->language];
1067 }
1068 $JSLanguageArray .= 'HTMLArea.I18N = ' . json_encode($labelsArray) . ';' . LF;
1069 return $JSLanguageArray;
1070 }
1071
1072 /**
1073 * Writes contents in a file in typo3temp/rtehtmlarea directory and returns the file name
1074 *
1075 * @param string $sourceFileName: The name of the file from which the contents should be extracted
1076 * @param string $label: A label to insert at the beginning of the name of the file
1077 * @param string $fileExtension: The file extension of the file, defaulting to 'js'
1078 * @param string $contents: The contents to write into the file if no $sourceFileName is provided
1079 *
1080 * @return string The name of the file writtten to typo3temp/rtehtmlarea
1081 */
1082 public function writeTemporaryFile($sourceFileName='', $label, $fileExtension='js', $contents='', $concatenate = FALSE) {
1083 global $TYPO3_CONF_VARS;
1084
1085 if ($sourceFileName) {
1086 $output = '';
1087 $source = t3lib_div::getFileAbsFileName($sourceFileName);
1088 $output = file_get_contents($source);
1089 } else {
1090 $output = $contents;
1091 }
1092 $compress = $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] && ($fileExtension == 'js') && ($output != '');
1093 $relativeFilename = 'typo3temp/' . $this->ID . '/' . str_replace('-','_',$label) . '_' . t3lib_div::shortMD5(($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . ($sourceFileName ? $sourceFileName : $output)), 20) . ($compress ? '_compressed' : '') . '.' . $fileExtension;
1094 $destination = PATH_site . $relativeFilename;
1095 if(!file_exists($destination)) {
1096 $compressedJavaScript = '';
1097 if ($compress && $fileExtension == 'js') {
1098 $compressedJavaScript = t3lib_div::minifyJavaScript($output);
1099 }
1100 $failure = t3lib_div::writeFileToTypo3tempDir($destination, $compressedJavaScript ? $compressedJavaScript : $output);
1101 if ($failure) {
1102 die($failure);
1103 }
1104 }
1105 if ($concatenate && $fileExtension == 'js') {
1106 $this->cumulativeScripts[$this->TCEform->RTEcounter][] = $destination;
1107 }
1108 if ($this->is_FE()) {
1109 $filename = ($GLOBALS['TSFE']->absRefPrefix ? $GLOBALS['TSFE']->absRefPrefix : '') . t3lib_div::createVersionNumberedFilename($relativeFilename);
1110 } else {
1111 $filename = t3lib_div::createVersionNumberedFilename(($this->isFrontendEditActive() ? '' : ($this->backPath . '../')) . $relativeFilename);
1112 }
1113 return t3lib_div::resolveBackPath($filename);
1114 }
1115 /**
1116 * Concatenates all accumulated scripts in a file in typo3temp/rtehtmlarea directory and returns the file name
1117 *
1118 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1119 *
1120 * @return string The name of the file writtten to typo3temp/rtehtmlarea
1121 */
1122 protected function doConcatenate($RTEcounter) {
1123 $fileExtension = 'js';
1124 $compress = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts'];
1125 $token = implode('|', $this->cumulativeScripts[$RTEcounter]);
1126 $relativeFilename = 'typo3temp/' . $this->ID . '/' . 'htmlarea_cumulative' . '_' . t3lib_div::shortMD5(($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . $token ), 20) . ($compress ? '_compressed' : '') . '.' . $fileExtension;
1127 $destination = PATH_site . $relativeFilename;
1128 if (!file_exists($destination)) {
1129 foreach ($this->cumulativeScripts[$RTEcounter] as $fileName) {
1130 $contents = file_get_contents($fileName);
1131 if (!file_exists($destination)) {
1132 $failure = t3lib_div::writeFileToTypo3tempDir($destination, $contents);
1133 if ($failure) {
1134 die($failure);
1135 }
1136 } else {
1137 $success = file_put_contents($destination, $contents, FILE_APPEND);
1138 if (!$success) {
1139 die('Could not append script' + $fileName);
1140 }
1141 }
1142 }
1143 }
1144 if ($this->is_FE()) {
1145 $filename = ($GLOBALS['TSFE']->absRefPrefix ? $GLOBALS['TSFE']->absRefPrefix : '') . t3lib_div::createVersionNumberedFilename($relativeFilename);
1146 } else {
1147 if ($compress) {
1148 $compressor = t3lib_div::makeInstance('t3lib_Compressor');
1149 $filename = $compressor->compressJsFile(($this->isFrontendEditActive() ? '' : ($this->backPath . '../')) . $relativeFilename);
1150 } else {
1151 $filename = t3lib_div::createVersionNumberedFilename(($this->isFrontendEditActive() ? '' : ($this->backPath . '../')) . $relativeFilename);
1152 }
1153 }
1154 return t3lib_div::resolveBackPath($filename);
1155 }
1156
1157 /**
1158 * Return a file name containing the main JS language array for HTMLArea
1159 *
1160 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1161 *
1162 * @return string filename
1163 */
1164 function buildJSMainLangFile($RTEcounter) {
1165 $contents = $this->buildJSMainLangArray() . LF;
1166 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
1167 $contents .= $this->buildJSLangArray($pluginId) . LF;
1168 }
1169 return $this->writeTemporaryFile('', $this->language.'_'.$this->OutputCharset, 'js', $contents, TRUE);
1170 }
1171
1172 /**
1173 * Return a Javascript localization array for the plugin
1174 *
1175 * @param string $plugin: identification string of the plugin
1176 *
1177 * @return string Javascript localization array
1178 */
1179
1180 function buildJSLangArray($plugin) {
1181 $LOCAL_LANG = FALSE;
1182 $extensionKey = is_object($this->registeredPlugins[$plugin]) ? $this->registeredPlugins[$plugin]->getExtensionKey() : $this->ID;
1183 $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $plugin . '/locallang.xml', $this->language, 'utf-8', 1);
1184 $linebreak = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts'] ? '' : LF;
1185 $JSLanguageArray = 'HTMLArea.I18N["' . $plugin . '"] = new Object();' . $linebreak;
1186 if (is_array($LOCAL_LANG)) {
1187 if (!empty($LOCAL_LANG[$this->language])) {
1188 $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'],$LOCAL_LANG[$this->language]);
1189 } else {
1190 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1191 }
1192 $JSLanguageArray .= 'HTMLArea.I18N["' . $plugin . '"] = ' . json_encode($LOCAL_LANG[$this->language]) . ';'. LF;
1193 }
1194 return $JSLanguageArray;
1195 }
1196
1197 /**
1198 * Return the JS code of the toolbar configuration for the HTMLArea editor
1199 *
1200 * @return string the JS code as nested JS arrays
1201 */
1202 protected function getJSToolbarArray() {
1203 // The toolbar array
1204 $toolbar = array();
1205 // The current row; a "linebreak" ends the current row
1206 $row = array();
1207 // The current group; each group is between "bar"s; a "linebreak" ends the current group
1208 $group = array();
1209 // Process each toolbar item in the toolbar order list
1210 foreach ($this->toolbarOrderArray as $item) {
1211 switch ($item) {
1212 case 'linebreak':
1213 // Add row to toolbar if not empty
1214 if (!empty($group)) {
1215 $row[] = $group;
1216 $group = array();
1217 }
1218 if (!empty($row)) {
1219 $toolbar[] = $row;
1220 $row = array();
1221 }
1222 break;
1223 case 'bar':
1224 // Add group to row if not empty
1225 if (!empty($group)) {
1226 $row[] = $group;
1227 $group = array();
1228 }
1229 break;
1230 case 'space':
1231 if (end($group) != $this->convertToolbarForHTMLArea($item)) {
1232 $group[] = $this->convertToolbarForHTMLArea($item);
1233 }
1234 break;
1235 default:
1236 if (in_array($item, $this->toolbar)) {
1237 // Add the item to the group
1238 $convertedItem = $this->convertToolbarForHTMLArea($item);
1239 if ($convertedItem) {
1240 $group[] = $convertedItem;
1241 }
1242 }
1243 break;
1244 }
1245 }
1246 // Add the last group and last line, if not empty
1247 if (!empty($group)) {
1248 $row[] = $group;
1249 }
1250 if (!empty($row)) {
1251 $toolbar[] = $row;
1252 }
1253 return json_encode($toolbar);
1254 }
1255
1256 public function getLLContent($string) {
1257 global $LANG;
1258
1259 $BE_lang = $LANG->lang;
1260 $BE_charSet = $LANG->charSet;
1261 $LANG->lang = $this->contentTypo3Language;
1262 $LANG->charSet = $this->contentCharset;
1263 $LLString = $LANG->JScharCode($LANG->sL($string));
1264 $LANG->lang = $BE_lang;
1265 $LANG->charSet = $BE_charSet;
1266 return $LLString;
1267 }
1268
1269 public function getPageConfigLabel($string,$JScharCode=1) {
1270 global $LANG, $TSFE, $TYPO3_CONF_VARS;
1271
1272 if ($this->is_FE()) {
1273 if (strcmp(substr($string,0,4),'LLL:') && $TYPO3_CONF_VARS['BE']['forceCharset']) {
1274 // A pure string coming from Page TSConfig must be in forceCharset, otherwise we just don't know..
1275 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $TYPO3_CONF_VARS['BE']['forceCharset'], $this->OutputCharset);
1276 } else {
1277 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $this->charset, $this->OutputCharset);
1278 }
1279 $label = str_replace('"', '\"', str_replace('\\\'', '\'', $label));
1280 $label = $JScharCode ? $this->feJScharCode($label) : $label;
1281 } else {
1282 if (strcmp(substr($string,0,4),'LLL:')) {
1283 $label = $string;
1284 } else {
1285 $label = $LANG->sL(trim($string));
1286 }
1287 $label = str_replace('"', '\"', str_replace('\\\'', '\'', $label));
1288 $label = $JScharCode ? $LANG->JScharCode($label): $label;
1289 }
1290 return $label;
1291 }
1292
1293 function feJScharCode($str) {
1294 global $TSFE;
1295 // Convert string to UTF-8:
1296 if ($this->OutputCharset != 'utf-8') $str = $TSFE->csConvObj->utf8_encode($str,$this->OutputCharset);
1297 // Convert the UTF-8 string into a array of char numbers:
1298 $nArr = $TSFE->csConvObj->utf8_to_numberarray($str);
1299 return 'String.fromCharCode('.implode(',',$nArr).')';
1300 }
1301
1302 public function getFullFileName($filename) {
1303 if (substr($filename,0,4)=='EXT:') { // extension
1304 list($extKey,$local) = explode('/',substr($filename,4),2);
1305 $newFilename = '';
1306 if (strcmp($extKey,'') && t3lib_extMgm::isLoaded($extKey) && strcmp($local,'')) {
1307 $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? t3lib_extMgm::siteRelPath($extKey) : $this->backPath . t3lib_extMgm::extRelPath($extKey)) . $local;
1308 }
1309 } elseif (substr($filename,0,1) != '/') {
1310 $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? '' : ($this->backPath . '../')) . $filename;
1311 } else {
1312 $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? '' : ($this->backPath . '../')) . substr($filename, 1);
1313 }
1314 return t3lib_div::resolveBackPath($newFilename);
1315 }
1316
1317 /**
1318 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1319 * This is for submit function of the form.
1320 *
1321 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1322 * @param string $formName: the name of the form
1323 * @param string $textareaId: the id of the textarea
1324 *
1325 * @return string Javascript code
1326 */
1327 function setSaveRTE($RTEcounter, $formName, $textareaId) {
1328 return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaId . '"].value = RTEarea["' . $textareaId . '"].editor.getHTML(); } else { OK = 0; };';
1329 }
1330
1331 /**
1332 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1333 * This is for submit function of the form.
1334 *
1335 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1336 * @param string $formName: the name of the form
1337 * @param string $textareaId: the id of the textarea
1338 *
1339 * @return string Javascript code
1340 */
1341 function setDeleteRTE($RTEcounter, $formName, $textareaId) {
1342 return 'if (RTEarea["' . $textareaId . '"]) { RTEarea["' . $textareaId . '"].deleted = true;}';
1343 }
1344
1345 /**
1346 * Return true if we are in the FE, but not in the FE editing feature of BE.
1347 *
1348 * @return boolean
1349 */
1350
1351 function is_FE() {
1352 return is_object($GLOBALS['TSFE']) && !$this->isFrontendEditActive();
1353 }
1354
1355 /**
1356 * Checks whether frontend editing is active.
1357 *
1358 * @return boolean
1359 */
1360 public function isFrontendEditActive() {
1361 return is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit);
1362 }
1363 /**
1364 * Client Browser Information
1365 *
1366 * @param string $userAgent: The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
1367 * @return array Contains keys "useragent", "browser", "version", "system"
1368 * where "browser" is limited to the engines
1369 * and where "version" is a floating number
1370 */
1371 function clientInfo ($userAgent='') {
1372 if (!$userAgent) {
1373 $userAgent = t3lib_div::getIndpEnv('HTTP_USER_AGENT');
1374 }
1375 $browserInfo = t3lib_utility_Client::getBrowserInfo($userAgent);
1376 // Known engines: order is not irrelevant!
1377 $knownEngines = array('opera', 'msie', 'gecko', 'webkit');
1378 if (is_array($browserInfo['all'])) {
1379 foreach ($knownEngines as $engine) {
1380 if ($browserInfo['all'][$engine]) {
1381 $browserInfo['browser'] = $engine;
1382 $browserInfo['version'] = t3lib_utility_Client::getVersion($browserInfo['all'][$engine]);
1383 break;
1384 }
1385 }
1386 }
1387 return $browserInfo;
1388 }
1389 /***************************
1390 *
1391 * OTHER FUNCTIONS: (from Classic RTE)
1392 *
1393 ***************************/
1394 /**
1395 * @return [type] ...
1396 * @desc
1397 */
1398
1399 function RTEtsConfigParams() {
1400 if($this->is_FE()) {
1401 return '';
1402 } else {
1403 $p = t3lib_BEfunc::getSpecConfParametersFromArray($this->specConf['rte_transform']['parameters']);
1404 return $this->elementParts[0].':'.$this->elementParts[1].':'.$this->elementParts[2].':'.$this->thePid.':'.$this->typeVal.':'.$this->tscPID.':'.$p['imgpath'];
1405 }
1406 }
1407
1408 public function cleanList($str) {
1409 if (strstr($str,'*')) {
1410 $str = '*';
1411 } else {
1412 $str = implode(',',array_unique(t3lib_div::trimExplode(',',$str,1)));
1413 }
1414 return $str;
1415 }
1416
1417 function filterStyleEl($elValue,$matchList) {
1418 $matchParts = t3lib_div::trimExplode(',',$matchList,1);
1419 $styleParts = explode(';',$elValue);
1420 $nStyle=array();
1421 foreach ($styleParts as $k => $p) {
1422 $pp = t3lib_div::trimExplode(':',$p);
1423 if ($pp[0]&&$pp[1]) {
1424 foreach ($matchParts as $el) {
1425 $star=substr($el,-1)=='*';
1426 if (!strcmp($pp[0],$el) || ($star && t3lib_div::isFirstPartOfStr($pp[0],substr($el,0,-1)) )) {
1427 $nStyle[]=$pp[0].':'.$pp[1];
1428 } else unset($styleParts[$k]);
1429 }
1430 } else {
1431 unset($styleParts[$k]);
1432 }
1433 }
1434 return implode('; ',$nStyle);
1435 }
1436
1437 // Hook on lorem_ipsum extension to insert text into the RTE in wysiwyg mode
1438 function loremIpsumInsert($params) {
1439 return "
1440 if (typeof(lorem_ipsum) == 'function' && " . $params['element'] . ".tagName.toLowerCase() == 'textarea' ) lorem_ipsum(" . $params['element'] . ", lipsum_temp_strings[lipsum_temp_pointer]);
1441 ";
1442 }
1443 }
1444 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']) {
1445 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']);
1446 }
1447 ?>