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