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