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