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