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