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