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