[FEATURE] htmlArea RTE: Add button to insert soft hyphen
[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-2012 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 $absolutePath = $fileName
456 ? t3lib_div::resolveBackPath(PATH_site . (($this->is_FE() || $this->isFrontendEditActive()) ? '' : TYPO3_mainDir) . $fileName)
457 : '';
458
459 // Fallback to default content css file if configured file does not exists or is of zero size
460 if (!$fileName || !file_exists($absolutePath) || !filesize($absolutePath)) {
461 $fileName = $this->getFullFileName('EXT:' . $this->ID . '/res/contentcss/default.css');
462 }
463 return $fileName;
464 }
465
466 /**
467 * Add links to skin style sheet(s) to document header
468 *
469 * @return void
470 */
471 protected function addSkin() {
472 // Get skin file name from Page TSConfig if any
473 $skinFilename = trim($this->thisConfig['skin']) ? trim($this->thisConfig['skin']) : 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
474 $this->editorCSS = $this->getFullFileName($skinFilename);
475 $skinDir = dirname($this->editorCSS);
476 // Editing area style sheet
477 $this->editedContentCSS = $skinDir . '/htmlarea-edited-content.css';
478 $this->addStyleSheet(
479 'rtehtmlarea-editing-area-skin',
480 $this->editedContentCSS
481 );
482 // Main skin
483 $this->addStyleSheet(
484 'rtehtmlarea-skin',
485 $this->editorCSS
486 );
487 // Additional icons from registered plugins
488 foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
489 if (is_object($this->registeredPlugins[$pluginId])) {
490 $pathToSkin = $this->registeredPlugins[$pluginId]->getPathToSkin();
491 if ($pathToSkin) {
492 $key = $this->registeredPlugins[$pluginId]->getExtensionKey();
493 $this->addStyleSheet(
494 'rtehtmlarea-plugin-' . $pluginId . '-skin',
495 ($this->is_FE() ? t3lib_extMgm::siteRelPath($key) : $this->backPath . t3lib_extMgm::extRelPath($key)) . $pathToSkin
496 );
497 }
498 }
499 }
500 }
501
502 /**
503 * Add style sheet file to document header
504 *
505 * @param string $key: some key identifying the style sheet
506 * @param string $href: uri to the style sheet file
507 * @param string $title: value for the title attribute of the link element
508 * @return string $relation: value for the rel attribute of the link element
509 * @return void
510 */
511 protected function addStyleSheet($key, $href, $title='', $relation='stylesheet') {
512 // 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
513 if (is_object($this->TCEform->inline) && $this->TCEform->inline->isAjaxCall) {
514 $this->TCEform->additionalCode_pre[$key] = '<link rel="' . $relation . '" type="text/css" href="' . $href . '" title="' . $title. '" />';
515 } else {
516 $pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
517 $pageRenderer->addCssFile($href, $relation, 'screen', $title);
518 }
519 }
520
521 /**
522 * Initialize toolbar configuration and enable registered plugins
523 *
524 * @return void
525 */
526 protected function initializeToolbarConfiguration() {
527
528 // Enable registred plugins
529 $this->enableRegisteredPlugins();
530
531 // Configure toolbar
532 $this->setToolbar();
533
534 // Check if some plugins need to be disabled
535 $this->setPlugins();
536
537 // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
538 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = $this->pluginEnabledArray;
539 if ($this->TCEform->RTEcounter > 1 && isset($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1]) && is_array($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])) {
540 $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = array_unique(array_values(array_merge($this->pluginEnabledArray,$this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter-1])));
541 }
542 }
543
544 /**
545 * Add registered plugins to the array of enabled plugins
546 *
547 */
548 function enableRegisteredPlugins() {
549 global $TYPO3_CONF_VARS;
550 // Traverse registered plugins
551 if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'])) {
552 foreach($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'] as $pluginId => $pluginObjectConfiguration) {
553 $plugin = FALSE;
554 if (is_array($pluginObjectConfiguration) && count($pluginObjectConfiguration)) {
555 $plugin = t3lib_div::getUserObj($pluginObjectConfiguration['objectReference']);
556 }
557 if (is_object($plugin)) {
558 if ($plugin->main($this)) {
559 $this->registeredPlugins[$pluginId] = $plugin;
560 // Override buttons from previously registered plugins
561 $pluginButtons = t3lib_div::trimExplode(',', $plugin->getPluginButtons(), 1);
562 foreach ($this->pluginButton as $previousPluginId => $buttonList) {
563 $this->pluginButton[$previousPluginId] = implode(',',array_diff(t3lib_div::trimExplode(',', $this->pluginButton[$previousPluginId], 1), $pluginButtons));
564 }
565 $this->pluginButton[$pluginId] = $plugin->getPluginButtons();
566 $pluginLabels = t3lib_div::trimExplode(',', $plugin->getPluginLabels(), 1);
567 foreach ($this->pluginLabel as $previousPluginId => $labelList) {
568 $this->pluginLabel[$previousPluginId] = implode(',',array_diff(t3lib_div::trimExplode(',', $this->pluginLabel[$previousPluginId], 1), $pluginLabels));
569 }
570 $this->pluginLabel[$pluginId] = $plugin->getPluginLabels();
571 $this->pluginEnabledArray[] = $pluginId;
572 }
573 }
574 }
575 }
576 // Process overrides
577 $hidePlugins = array();
578 foreach ($this->registeredPlugins as $pluginId => $plugin) {
579 if ($plugin->addsButtons() && !$this->pluginButton[$pluginId]) {
580 $hidePlugins[] = $pluginId;
581 }
582 }
583 $this->pluginEnabledArray = array_unique(array_diff($this->pluginEnabledArray, $hidePlugins));
584 }
585
586 /**
587 * Set the toolbar config (only in this PHP-Object, not in JS):
588 *
589 */
590
591 function setToolbar() {
592 if ($this->client['browser'] == 'msie' || $this->client['browser'] == 'opera') {
593 $this->thisConfig['keepButtonGroupTogether'] = 0;
594 }
595
596 $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
597 bar, formattext, bold, strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
598 bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, line,
599 bar, left, center, right, justifyfull,
600 bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, lefttoright, righttoleft, language, showlanguagemarks,
601 bar, textcolor, bgcolor, textindicator,
602 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,
603 bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pastetoggle, pastebehaviour, bar, undo, redo, bar, showhelp, about, linebreak,
604 ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '': '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 // Additional buttons from registered plugins
609 foreach($this->registeredPlugins as $pluginId => $plugin) {
610 if ($this->isPluginEnabled($pluginId)) {
611 $this->defaultToolbarOrder = $plugin->addButtonsToToolbar();
612 }
613 }
614 $toolbarOrder = $this->thisConfig['toolbarOrder'] ? $this->thisConfig['toolbarOrder'] : $this->defaultToolbarOrder;
615
616 // Getting rid of undefined buttons
617 $this->toolbarOrderArray = array_intersect(t3lib_div::trimExplode(',', $toolbarOrder, 1), t3lib_div::trimExplode(',', $this->defaultToolbarOrder, 1));
618 $toolbarOrder = array_unique(array_values($this->toolbarOrderArray));
619
620 // Fetching specConf for field from backend
621 $pList = is_array($this->specConf['richtext']['parameters']) ? implode(',',$this->specConf['richtext']['parameters']) : '';
622 if ($pList != '*') { // If not all
623 $show = is_array($this->specConf['richtext']['parameters']) ? $this->specConf['richtext']['parameters'] : array();
624 if ($this->thisConfig['showButtons']) {
625 if (!t3lib_div::inList($this->thisConfig['showButtons'],'*')) {
626 $show = array_unique(array_merge($show,t3lib_div::trimExplode(',',$this->thisConfig['showButtons'],1)));
627 } else {
628 $show = array_unique(array_merge($show, $toolbarOrder));
629 }
630 }
631 if (is_array($this->thisConfig['showButtons.'])) {
632 foreach ($this->thisConfig['showButtons.'] as $buttonId => $value) {
633 if ($value) $show[] = $buttonId;
634 }
635 $show = array_unique($show);
636 }
637 } else {
638 $show = $toolbarOrder;
639 }
640
641 // Resticting to RTEkeyList for backend user
642 if(is_object($GLOBALS['BE_USER'])) {
643 $RTEkeyList = isset($GLOBALS['BE_USER']->userTS['options.']['RTEkeyList']) ? $GLOBALS['BE_USER']->userTS['options.']['RTEkeyList'] : '*';
644 if ($RTEkeyList != '*') { // If not all
645 $show = array_intersect($show, t3lib_div::trimExplode(',',$RTEkeyList,1));
646 }
647 }
648
649 // Hiding buttons of disabled plugins
650 $hideButtons = array('space', 'bar', 'linebreak');
651 foreach ($this->pluginButton as $pluginId => $buttonList) {
652 if (!$this->isPluginEnabled($pluginId)) {
653 $buttonArray = t3lib_div::trimExplode(',',$buttonList,1);
654 foreach ($buttonArray as $button) {
655 $hideButtons[] = $button;
656 }
657 }
658 }
659
660 // Hiding labels of disabled plugins
661 foreach ($this->pluginLabel as $pluginId => $label) {
662 if (!$this->isPluginEnabled($pluginId)) {
663 $hideButtons[] = $label;
664 }
665 }
666
667 // Hiding buttons
668 $show = array_diff($show, $this->conf_toolbar_hide, t3lib_div::trimExplode(',',$this->thisConfig['hideButtons'],1));
669
670 // Apply toolbar constraints from registered plugins
671 foreach ($this->registeredPlugins as $pluginId => $plugin) {
672 if ($this->isPluginEnabled($pluginId) && method_exists($plugin, "applyToolbarConstraints")) {
673 $show = $plugin->applyToolbarConstraints($show);
674 }
675 }
676 // Getting rid of the buttons for which we have no position
677 $show = array_intersect($show, $toolbarOrder);
678 $this->toolbar = $show;
679 }
680
681 /**
682 * Disable some plugins
683 *
684 */
685 function setPlugins() {
686
687 // Disabling a plugin that adds buttons if none of its buttons is in the toolbar
688 $hidePlugins = array();
689 foreach ($this->pluginButton as $pluginId => $buttonList) {
690 if ($this->registeredPlugins[$pluginId]->addsButtons()) {
691 $showPlugin = FALSE;
692 $buttonArray = t3lib_div::trimExplode(',', $buttonList, 1);
693 foreach ($buttonArray as $button) {
694 if (in_array($button, $this->toolbar)) {
695 $showPlugin = TRUE;
696 }
697 }
698 if (!$showPlugin) {
699 $hidePlugins[] = $pluginId;
700 }
701 }
702 }
703 $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
704
705 // Hiding labels of disabled plugins
706 $hideLabels = array();
707 foreach ($this->pluginLabel as $pluginId => $label) {
708 if (!$this->isPluginEnabled($pluginId)) {
709 $hideLabels[] = $label;
710 }
711 }
712 $this->toolbar = array_diff($this->toolbar, $hideLabels);
713
714 // Adding plugins declared as prerequisites by enabled plugins
715 $requiredPlugins = array();
716 foreach ($this->registeredPlugins as $pluginId => $plugin) {
717 if ($this->isPluginEnabled($pluginId)) {
718 $requiredPlugins = array_merge($requiredPlugins, t3lib_div::trimExplode(',', $plugin->getRequiredPlugins(), 1));
719 }
720 }
721 $requiredPlugins = array_unique($requiredPlugins);
722 foreach ($requiredPlugins as $pluginId) {
723 if (is_object($this->registeredPlugins[$pluginId]) && !$this->isPluginEnabled($pluginId)) {
724 $this->pluginEnabledArray[] = $pluginId;
725 }
726 }
727 $this->pluginEnabledArray = array_unique($this->pluginEnabledArray);
728
729 // Completing the toolbar conversion array for htmlArea
730 foreach ($this->registeredPlugins as $pluginId => $plugin) {
731 if ($this->isPluginEnabled($pluginId)) {
732 $this->convertToolbarForHtmlAreaArray = array_unique(array_merge($this->convertToolbarForHtmlAreaArray, $plugin->getConvertToolbarForHtmlAreaArray()));
733 }
734 }
735 }
736
737 /**
738 * Convert the TYPO3 names of buttons into the names for htmlArea RTE
739 *
740 * @param string buttonname (typo3-name)
741 * @return string buttonname (htmlarea-name)
742 */
743
744 function convertToolbarForHTMLArea($button) {
745 return $this->convertToolbarForHtmlAreaArray[$button];
746 }
747 /**
748 * Return the HTML code for loading the Javascript files
749 *
750 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
751 *
752 * @return void
753 */
754 protected function includeScriptFiles($RTEcounter) {
755 $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea.js', 'htmlarea', 'js', '', TRUE);
756 if ($this->client['browser'] == 'msie') {
757 $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-ie.js', 'htmlarea-ie', 'js', '', TRUE);
758 } else {
759 $this->writeTemporaryFile('EXT:' . $this->ID . '/htmlarea/htmlarea-gecko.js', 'htmlarea-gecko', 'js', '', TRUE);
760 }
761 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
762 $extensionKey = is_object($this->registeredPlugins[$pluginId]) ? $this->registeredPlugins[$pluginId]->getExtensionKey() : $this->ID;
763 $this->writeTemporaryFile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $pluginId . '/' . strtolower(preg_replace('/([a-z])([A-Z])([a-z])/', "$1".'-'."$2"."$3", $pluginId)) . '.js', $pluginId, 'js', '', TRUE);
764 }
765 }
766 /**
767 * Return the HTML code for loading the Javascript files
768 *
769 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
770 *
771 * @return string the html code for loading the Javascript Files
772 */
773 protected function loadJSfiles($RTEcounter) {
774 $loadJavascriptCode = '<script type="text/javascript" src="' . $this->doConcatenate($RTEcounter) . '"></script>' . LF;
775 $loadJavascriptCode .= t3lib_div::wrapJS('
776 if (typeof(RTEarea) == "undefined") {
777 RTEarea = new Object();
778 RTEarea[0] = new Object();
779 RTEarea[0].version = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['version'] . '";
780 RTEarea[0].editorUrl = "' . $this->extHttpPath . 'htmlarea/";
781 RTEarea[0].editorCSS = "' . t3lib_div::createVersionNumberedFilename($this->editorCSS) . '";
782 RTEarea[0].editorSkin = "' . dirname($this->editorCSS) . '/";
783 RTEarea[0].editedContentCSS = "' . t3lib_div::createVersionNumberedFilename($this->editedContentCSS) . '";
784 RTEarea[0].hostUrl = "' . $this->hostURL . '";
785 RTEarea.init = function() {
786 if (typeof(HTMLArea) == "undefined" || !Ext.isReady) {
787 window.setTimeout("RTEarea.init();", 40);
788 } else {
789 Ext.QuickTips.init();
790 HTMLArea.init();
791 }
792 };
793 RTEarea.initEditor = function(editorNumber) {
794 if (typeof(HTMLArea) == "undefined") {
795 RTEarea.initEditor.defer(40, null, [editorNumber]);
796 } else {
797 HTMLArea.initEditor(editorNumber);
798 }
799 };
800 }'
801 );
802 return $loadJavascriptCode;
803 }
804
805 /**
806 * Return the Javascript code for initializing the RTE
807 *
808 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
809 *
810 * @return string the Javascript code for initializing the RTE
811 */
812 function loadJScode($RTEcounter) {
813 return TAB . 'RTEarea.init();';
814 }
815
816 /**
817 * Return the Javascript code for configuring the RTE
818 *
819 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
820 * @param string $table: The table that includes this RTE (optional, necessary for IRRE).
821 * @param string $uid: The uid of that table that includes this RTE (optional, necessary for IRRE).
822 * @param string $field: The field of that record that includes this RTE (optional).
823 *
824 * @return string the Javascript code for configuring the RTE
825 */
826 function registerRTEinJS($RTEcounter, $table='', $uid='', $field='', $textAreaId = '') {
827 $configureRTEInJavascriptString = '
828 if (typeof(configureEditorInstance) == "undefined") {
829 configureEditorInstance = new Object();
830 }
831 configureEditorInstance["' . $textAreaId . '"] = function() {
832 if (typeof(RTEarea) == "undefined" || typeof(HTMLArea) == "undefined") {
833 window.setTimeout("configureEditorInstance[\'' . $textAreaId . '\']();", 40);
834 } else {
835 editornumber = "' . $textAreaId . '";
836 RTEarea[editornumber] = new Object();
837 RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";
838 RTEarea[editornumber].number = editornumber;
839 RTEarea[editornumber].deleted = false;
840 RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
841 RTEarea[editornumber].id = "RTEarea" + editornumber;
842 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'])) . '";
843 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'])) . '";
844 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')) . ';
845 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')) . '";
846 RTEarea[editornumber].fullScreen = ' . ($this->fullScreen ? 'true' : 'false') . ';
847 RTEarea[editornumber].showStatusBar = ' . (trim($this->thisConfig['showStatusBar'])?'true':'false') . ';
848 RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean'])?'true':'false') . ';
849 RTEarea[editornumber].htmlRemoveComments = ' . (trim($this->thisConfig['removeComments'])?'true':'false') . ';
850 RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs'])?'true':'false') . ';
851 RTEarea[editornumber].disableObjectResizing = ' . (trim($this->thisConfig['disableObjectResizing'])?'true':'false') . ';
852 RTEarea[editornumber].removeTrailingBR = ' . (trim($this->thisConfig['removeTrailingBR'])?'true':'false') . ';
853 RTEarea[editornumber].useCSS = ' . (trim($this->thisConfig['useCSS'])?'true':'false') . ';
854 RTEarea[editornumber].keepButtonGroupTogether = ' . (trim($this->thisConfig['keepButtonGroupTogether'])?'true':'false') . ';
855 RTEarea[editornumber].disablePCexamples = ' . (trim($this->thisConfig['disablePCexamples'])?'true':'false') . ';
856 RTEarea[editornumber].showTagFreeClasses = ' . (trim($this->thisConfig['showTagFreeClasses'])?'true':'false') . ';
857 RTEarea[editornumber].useHTTPS = ' . ((trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'])?'true':'false') . ';
858 RTEarea[editornumber].tceformsNested = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(TRUE) : '[]') . ';
859 RTEarea[editornumber].dialogueWindows = new Object();';
860 // The following property is deprecated as of TYPO3 4.6 and will be removed in TYPO3 4.8
861 if (isset($this->thisConfig['showTagFreeClasses'])) {
862 $this->logDeprecatedProperty('showTagFreeClasses', 'buttons.blockstyle.showTagFreeClasses', '4.8');
863 $this->logDeprecatedProperty('showTagFreeClasses', 'buttons.textstyle.showTagFreeClasses', '4.8');
864 }
865 // The following property is deprecated as of TYPO3 4.6 and will be removed in TYPO3 4.8
866 if (isset($this->thisConfig['disablePCexamples'])) {
867 $this->logDeprecatedProperty('disablePCexamples', 'buttons.blockstyle.disableStyleOnOptionLabel', '4.8');
868 $this->logDeprecatedProperty('disablePCexamples', 'buttons.textstyle.disableStyleOnOptionLabel', '4.8');
869 }
870 if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop'])) {
871 $configureRTEInJavascriptString .= '
872 RTEarea[editornumber].dialogueWindows.positionFromTop = ' . intval($this->thisConfig['dialogueWindows.']['defaultPositionFromTop']) . ';';
873 }
874 if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'])) {
875 $configureRTEInJavascriptString .= '
876 RTEarea[editornumber].dialogueWindows.positionFromLeft = ' . intval($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft']) . ';';
877 }
878 // The following properties apply only to the backend
879 if (!$this->is_FE()) {
880 $configureRTEInJavascriptString .= '
881 RTEarea[editornumber].sys_language_content = "' . $this->contentLanguageUid . '";
882 RTEarea[editornumber].typo3ContentLanguage = "' . $this->contentTypo3Language . '";
883 RTEarea[editornumber].typo3ContentCharset = "' . $this->contentCharset . '";
884 RTEarea[editornumber].userUid = "' . $this->userUid . '";';
885 }
886
887 // Setting the plugin flags
888 $configureRTEInJavascriptString .= '
889 RTEarea[editornumber].plugin = new Object();
890 RTEarea[editornumber].pathToPluginDirectory = new Object();';
891 foreach ($this->pluginEnabledArray as $pluginId) {
892 $configureRTEInJavascriptString .= '
893 RTEarea[editornumber].plugin.'.$pluginId.' = true;';
894 if (is_object($this->registeredPlugins[$pluginId])) {
895 $pathToPluginDirectory = $this->registeredPlugins[$pluginId]->getPathToPluginDirectory();
896 if ($pathToPluginDirectory) {
897 $configureRTEInJavascriptString .= '
898 RTEarea[editornumber].pathToPluginDirectory.'.$pluginId.' = "' . $pathToPluginDirectory . '";';
899 }
900 }
901 }
902
903 // Setting the buttons configuration
904 $configureRTEInJavascriptString .= '
905 RTEarea[editornumber].buttons = new Object();';
906 if (is_array($this->thisConfig['buttons.'])) {
907 foreach ($this->thisConfig['buttons.'] as $buttonIndex => $conf) {
908 $button = substr($buttonIndex, 0, -1);
909 if (is_array($conf)) {
910 $configureRTEInJavascriptString .= '
911 RTEarea[editornumber].buttons.'.$button.' = ' . $this->buildNestedJSArray($conf) . ';';
912 }
913 }
914 }
915
916 // Setting the list of tags to be removed if specified in the RTE config
917 if (trim($this->thisConfig['removeTags'])) {
918 $configureRTEInJavascriptString .= '
919 RTEarea[editornumber].htmlRemoveTags = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTags'], 1)) . ')$/i;';
920 }
921
922 // Setting the list of tags to be removed with their contents if specified in the RTE config
923 if (trim($this->thisConfig['removeTagsAndContents'])) {
924 $configureRTEInJavascriptString .= '
925 RTEarea[editornumber].htmlRemoveTagsAndContents = /^(' . implode('|', t3lib_div::trimExplode(',', $this->thisConfig['removeTagsAndContents'], 1)) . ')$/i;';
926 }
927 // Process default style configuration
928 // This default configuration is deprecated as of TYPO3 4.6 and will be removed in TYPO3 4.8.
929 // Use contentCSS instead.
930 $configureRTEInJavascriptString .= '
931 RTEarea[editornumber].defaultPageStyle = "' . $this->writeTemporaryFile('', 'defaultPageStyle', 'css', $this->buildStyleSheet()) . '";';
932 // Setting the pageStyle
933 $configureRTEInJavascriptString .= '
934 RTEarea[editornumber].pageStyle = "' . t3lib_div::createVersionNumberedFilename($this->getContentCssFileName()) .'";';
935 // Process classes configuration
936 $classesConfigurationRequired = FALSE;
937 foreach ($this->registeredPlugins as $pluginId => $plugin) {
938 if ($this->isPluginEnabled($pluginId)) {
939 $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
940 }
941 }
942 if ($classesConfigurationRequired) {
943 $configureRTEInJavascriptString .= $this->buildJSClassesConfig($RTEcounter);
944 }
945 // Add Javascript configuration for registered plugins
946 foreach ($this->registeredPlugins as $pluginId => $plugin) {
947 if ($this->isPluginEnabled($pluginId)) {
948 $configureRTEInJavascriptString .= $plugin->buildJavascriptConfiguration('editornumber');
949 }
950 }
951 // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
952 $configureRTEInJavascriptString .= '
953 RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';
954 RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';
955 RTEarea.initEditor(editornumber);
956 }
957 };
958 configureEditorInstance["' . $textAreaId . '"]();';
959 return $configureRTEInJavascriptString;
960 }
961
962 /**
963 * Return TRUE, if the plugin can be loaded
964 *
965 * @param string $pluginId: The identification string of the plugin
966 *
967 * @return boolean TRUE if the plugin can be loaded
968 */
969
970 function isPluginEnabled($pluginId) {
971 return in_array($pluginId, $this->pluginEnabledArray);
972 }
973
974 /**
975 * Build the default content style sheet
976 *
977 * @return string Style sheet
978 * @deprecated since TYPO3 4.8, will be removed in TYPO3 4.10
979 */
980 function buildStyleSheet() {
981 // This function will be DEPRECATED as of TYPO3 4.8 and will be removed in TYPO3 4.10
982 //t3lib_div::logDeprecatedFunction();
983 // These PageTSConfig properties are DEPRECATED as of TYPO3 4.6 and will be removed in TYPO3 4.8
984 $properties = array('mainStyle_font', 'mainStyle_size', 'mainStyle_color', 'mainStyle_bgcolor', 'mainStyleOverride');
985 foreach ($properties as $property) {
986 if (isset($this->thisConfig[$property])) {
987 $this->logDeprecatedProperty($property, 'contentCSS', '4.8');
988 }
989 }
990 if (is_array($this->thisConfig['mainStyleOverride_add.'])) {
991 $this->logDeprecatedProperty('mainStyleOverride_add', 'contentCSS', '4.8');
992 }
993 if (is_array($this->thisConfig['inlineStyle.'])) {
994 $this->logDeprecatedProperty('inlineStyle', 'contentCSS', '4.8');
995 }
996 if (!trim($this->thisConfig['ignoreMainStyleOverride'])) {
997 $mainStyle_font = $this->thisConfig['mainStyle_font'] ? $this->thisConfig['mainStyle_font']: 'Verdana,sans-serif';
998 $mainElements = array();
999 $mainElements['P'] = $this->thisConfig['mainStyleOverride_add.']['P'];
1000 $elList = explode(',','H1,H2,H3,H4,H5,H6,PRE');
1001 foreach ($elList as $elListName) {
1002 if ($this->thisConfig['mainStyleOverride_add.'][$elListName]) {
1003 $mainElements[$elListName] = $this->thisConfig['mainStyleOverride_add.'][$elListName];
1004 }
1005 }
1006
1007 $addElementCode = '';
1008 foreach ($mainElements as $elListName => $elValue) {
1009 $addElementCode .= strToLower($elListName) . ' {' . $elValue . '}' . LF;
1010 }
1011
1012 $stylesheet = $this->thisConfig['mainStyleOverride'] ? $this->thisConfig['mainStyleOverride'] : LF .
1013 'body.htmlarea-content-body { font-family: ' . $mainStyle_font .
1014 '; font-size: '.($this->thisConfig['mainStyle_size'] ? $this->thisConfig['mainStyle_size'] : '12px') .
1015 '; color: '.($this->thisConfig['mainStyle_color']?$this->thisConfig['mainStyle_color'] : 'black') .
1016 '; background-color: '.($this->thisConfig['mainStyle_bgcolor'] ? $this->thisConfig['mainStyle_bgcolor'] : 'white') .
1017 ';'.$this->thisConfig['mainStyleOverride_add.']['BODY'].'}' . LF .
1018 'td { ' . $this->thisConfig['mainStyleOverride_add.']['TD'].'}' . LF .
1019 'div { ' . $this->thisConfig['mainStyleOverride_add.']['DIV'].'}' . LF .
1020 'pre { ' . $this->thisConfig['mainStyleOverride_add.']['PRE'].'}' . LF .
1021 'ol { ' . $this->thisConfig['mainStyleOverride_add.']['OL'].'}' . LF .
1022 'ul { ' . $this->thisConfig['mainStyleOverride_add.']['UL'].'}' . LF .
1023 'blockquote { ' . $this->thisConfig['mainStyleOverride_add.']['BLOCKQUOTE'].'}' . LF .
1024 $addElementCode;
1025
1026 if (is_array($this->thisConfig['inlineStyle.'])) {
1027 $stylesheet .= LF . implode(LF, $this->thisConfig['inlineStyle.']) . LF;
1028 }
1029 } else {
1030 $stylesheet = '/* mainStyleOverride and inlineStyle properties ignored. */';
1031 }
1032 return $stylesheet;
1033 }
1034
1035 /**
1036 * Return Javascript configuration of classes
1037 *
1038 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1039 *
1040 * @return string Javascript configuration of classes
1041 */
1042 function buildJSClassesConfig($RTEcounter) {
1043 // Build JS array of lists of classes
1044 // These PageTSConfig properties are DEPRECATED as of TYPO3 4.6 and will be removed in TYPO3 4.8
1045 $classesTagList = 'classesCharacter, classesParagraph, classesImage, classesTable, classesLinks, classesTD';
1046 $classesTagConvert = array('classesCharacter' => 'span', 'classesParagraph' => 'div', 'classesImage' => 'img', 'classesTable' => 'table', 'classesLinks' => 'a', 'classesTD' => 'td');
1047 $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');
1048 $classesTagArray = t3lib_div::trimExplode(',' , $classesTagList);
1049 $configureRTEInJavascriptString = '
1050 RTEarea[editornumber].classesTag = new Object();';
1051 foreach ($classesTagArray as $classesTagName) {
1052 $HTMLAreaJSClasses = $this->thisConfig[$classesTagName] ? ('"' . $this->cleanList($this->thisConfig[$classesTagName]) . '";') : 'null;';
1053 $configureRTEInJavascriptString .= '
1054 RTEarea[editornumber].classesTag.'. $classesTagConvert[$classesTagName] .' = '. $HTMLAreaJSClasses;
1055 if (isset($this->thisConfig[$classesTagName])) {
1056 $this->logDeprecatedProperty($classesTagName, $classesUseInstead[$classesTagName], '4.8');
1057 }
1058 }
1059 // Include JS arrays of configured classes
1060 $configureRTEInJavascriptString .= '
1061 RTEarea[editornumber].classesUrl = "' . $this->writeTemporaryFile('', 'classes_' . $this->language, 'js', $this->buildJSClassesArray(), TRUE) . '";';
1062 return $configureRTEInJavascriptString;
1063 }
1064
1065 /**
1066 * Return JS arrays of classes configuration
1067 *
1068 * @return string JS classes arrays
1069 */
1070 function buildJSClassesArray() {
1071 if ($this->is_FE()) {
1072 $RTEProperties = $this->RTEsetup;
1073 } else {
1074 $RTEProperties = $this->RTEsetup['properties'];
1075 }
1076 $classesArray = array('labels' => array(), 'values' => array(), 'noShow' => array(), 'alternating' => array(), 'counting' => array(), 'XOR' => array());
1077 $JSClassesArray = '';
1078 // Scanning the list of classes if specified in the RTE config
1079 if (is_array($RTEProperties['classes.'])) {
1080 foreach ($RTEProperties['classes.'] as $className => $conf) {
1081 $className = rtrim($className, '.');
1082 $classesArray['labels'][$className] = $this->getPageConfigLabel($conf['name'], FALSE);
1083 $classesArray['values'][$className] = str_replace('\\\'', '\'', $conf['value']);
1084 if (isset($conf['noShow'])) {
1085 $classesArray['noShow'][$className] = $conf['noShow'];
1086 }
1087 if (is_array($conf['alternating.'])) {
1088 $classesArray['alternating'][$className] = $conf['alternating.'];
1089 }
1090 if (is_array($conf['counting.'])) {
1091 $classesArray['counting'][$className] = $conf['counting.'];
1092 }
1093 }
1094 }
1095 // Scanning the list of sets of mutually exclusives classes if specified in the RTE config
1096 if (is_array($RTEProperties['mutuallyExclusiveClasses.'])) {
1097 foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
1098 $classSet = t3lib_div::trimExplode(',', $conf, 1);
1099 $classList = implode(',', $classSet);
1100 foreach ($classSet as $className) {
1101 $classesArray['XOR'][$className] = '/^(' . implode('|', t3lib_div::trimExplode(',', t3lib_div::rmFromList($className, $classList), 1)) . ')$/';
1102 }
1103 }
1104 }
1105 foreach ($classesArray as $key => $subArray) {
1106 $JSClassesArray .= 'HTMLArea.classes' . ucfirst($key) . ' = ' . $this->buildNestedJSArray($subArray) . ';' . LF;
1107 }
1108 return $JSClassesArray;
1109 }
1110
1111 /**
1112 * Translate Page TS Config array in JS nested array definition
1113 * Replace 0 values with false
1114 * Unquote regular expression values
1115 * Replace empty arrays with empty objects
1116 *
1117 * @param array $conf: Page TSConfig configuration array
1118 *
1119 * @return string nested JS array definition
1120 */
1121 function buildNestedJSArray($conf) {
1122 $convertedConf = t3lib_div::removeDotsFromTS($conf);
1123 if ($this->is_FE()) {
1124 $GLOBALS['TSFE']->csConvObj->convArray($convertedConf, ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] ? $GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset'] : 'iso-8859-1'), 'utf-8');
1125 } else {
1126 $GLOBALS['LANG']->csConvObj->convArray($convertedConf, $GLOBALS['LANG']->charSet, 'utf-8');
1127 }
1128 return str_replace(array(':"0"', ':"\/^(', ')$\/i"', ':"\/^(', ')$\/"', '[]'), array(':false', ':/^(', ')$/i', ':/^(', ')$/', '{}'), json_encode($convertedConf));
1129 }
1130
1131 /**
1132 * Return a Javascript localization array for htmlArea RTE
1133 *
1134 * @return string Javascript localization array
1135 */
1136 function buildJSMainLangArray() {
1137 $JSLanguageArray = 'HTMLArea.I18N = new Object();' . LF;
1138 $labelsArray = array('tooltips' => array(), 'msg' => array(), 'dialogs' => array());
1139 foreach ($labelsArray as $labels => $subArray) {
1140 $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $this->ID . '/htmlarea/locallang_' . $labels . '.xml', $this->language, 'utf-8');
1141 if (!empty($LOCAL_LANG[$this->language])) {
1142 $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'], $LOCAL_LANG[$this->language]);
1143 } else {
1144 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1145 }
1146 $labelsArray[$labels] = $LOCAL_LANG[$this->language];
1147 }
1148 $JSLanguageArray .= 'HTMLArea.I18N = ' . json_encode($labelsArray) . ';' . LF;
1149 return $JSLanguageArray;
1150 }
1151
1152 /**
1153 * Writes contents in a file in typo3temp/rtehtmlarea directory and returns the file name
1154 *
1155 * @param string $sourceFileName: The name of the file from which the contents should be extracted
1156 * @param string $label: A label to insert at the beginning of the name of the file
1157 * @param string $fileExtension: The file extension of the file, defaulting to 'js'
1158 * @param string $contents: The contents to write into the file if no $sourceFileName is provided
1159 *
1160 * @return string The name of the file writtten to typo3temp/rtehtmlarea
1161 */
1162 public function writeTemporaryFile($sourceFileName='', $label, $fileExtension='js', $contents='', $concatenate = FALSE) {
1163 global $TYPO3_CONF_VARS;
1164
1165 if ($sourceFileName) {
1166 $output = '';
1167 $source = t3lib_div::getFileAbsFileName($sourceFileName);
1168 $output = file_get_contents($source);
1169 } else {
1170 $output = $contents;
1171 }
1172 $compress = $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['enableCompressedScripts'] && ($fileExtension == 'js') && ($output != '');
1173 $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;
1174 $destination = PATH_site . $relativeFilename;
1175 if(!file_exists($destination)) {
1176 $compressedJavaScript = '';
1177 if ($compress && $fileExtension == 'js') {
1178 $compressedJavaScript = t3lib_div::minifyJavaScript($output);
1179 }
1180 $failure = t3lib_div::writeFileToTypo3tempDir($destination, $compressedJavaScript ? $compressedJavaScript : $output);
1181 if ($failure) {
1182 throw new RuntimeException($failure, 1294585668);
1183 }
1184 }
1185 if ($concatenate && $fileExtension == 'js') {
1186 $this->cumulativeScripts[$this->TCEform->RTEcounter][] = $destination;
1187 }
1188 if ($this->is_FE()) {
1189 $filename = ($GLOBALS['TSFE']->absRefPrefix ? $GLOBALS['TSFE']->absRefPrefix : '') . t3lib_div::createVersionNumberedFilename($relativeFilename);
1190 } else {
1191 $filename = t3lib_div::createVersionNumberedFilename(($this->isFrontendEditActive() ? '' : ($this->backPath . '../')) . $relativeFilename);
1192 }
1193 return t3lib_div::resolveBackPath($filename);
1194 }
1195 /**
1196 * Concatenates all accumulated scripts in a file in typo3temp/rtehtmlarea directory and returns the file name
1197 *
1198 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1199 *
1200 * @return string The name of the file writtten to typo3temp/rtehtmlarea
1201 */
1202 protected function doConcatenate($RTEcounter) {
1203 $fileExtension = 'js';
1204 $compress = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts'];
1205 $token = implode('|', $this->cumulativeScripts[$RTEcounter]);
1206 $relativeFilename = 'typo3temp/' . $this->ID . '/' . 'htmlarea_cumulative' . '_' . t3lib_div::shortMD5((TYPO3_version . $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . $token ), 20) . ($compress ? '_compressed' : '') . '.' . $fileExtension;
1207 $destination = PATH_site . $relativeFilename;
1208 if (!file_exists($destination)) {
1209 foreach ($this->cumulativeScripts[$RTEcounter] as $fileName) {
1210 $contents = file_get_contents($fileName);
1211 if (!file_exists($destination)) {
1212 $failure = t3lib_div::writeFileToTypo3tempDir($destination, $contents);
1213 if ($failure) {
1214 throw new RuntimeException($failure, 1294585669);
1215 }
1216 } else {
1217 $success = file_put_contents($destination, $contents, FILE_APPEND);
1218 if (!$success) {
1219 throw new RuntimeException('Could not append script: ' . $fileName, 1294585670);
1220 }
1221 }
1222 }
1223 }
1224 if ($this->is_FE()) {
1225 $filename = ($GLOBALS['TSFE']->absRefPrefix ? $GLOBALS['TSFE']->absRefPrefix : '') . t3lib_div::createVersionNumberedFilename($relativeFilename);
1226 } else {
1227 if ($compress) {
1228 $compressor = t3lib_div::makeInstance('t3lib_Compressor');
1229 $filename = $compressor->compressJsFile(($this->isFrontendEditActive() ? '' : $this->backPath) . '../' . $relativeFilename);
1230 if ($this->isFrontendEditActive()) {
1231 $filename = preg_replace('/^..\//', '', $filename);
1232 }
1233 } else {
1234 $filename = t3lib_div::createVersionNumberedFilename(($this->isFrontendEditActive() ? '' : ($this->backPath . '../')) . $relativeFilename);
1235 }
1236 }
1237 return t3lib_div::resolveBackPath($filename);
1238 }
1239
1240 /**
1241 * Return a file name containing the main JS language array for HTMLArea
1242 *
1243 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1244 *
1245 * @return string filename
1246 */
1247 function buildJSMainLangFile($RTEcounter) {
1248 $contents = $this->buildJSMainLangArray() . LF;
1249 foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
1250 $contents .= $this->buildJSLangArray($pluginId) . LF;
1251 }
1252 return $this->writeTemporaryFile('', $this->language.'_'.$this->OutputCharset, 'js', $contents, TRUE);
1253 }
1254
1255 /**
1256 * Return a Javascript localization array for the plugin
1257 *
1258 * @param string $plugin: identification string of the plugin
1259 *
1260 * @return string Javascript localization array
1261 */
1262
1263 function buildJSLangArray($plugin) {
1264 $LOCAL_LANG = FALSE;
1265 $extensionKey = is_object($this->registeredPlugins[$plugin]) ? $this->registeredPlugins[$plugin]->getExtensionKey() : $this->ID;
1266 $LOCAL_LANG = t3lib_div::readLLfile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $plugin . '/locallang.xml', $this->language, 'utf-8', 1);
1267 $linebreak = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['enableCompressedScripts'] ? '' : LF;
1268 $JSLanguageArray = 'HTMLArea.I18N["' . $plugin . '"] = new Object();' . $linebreak;
1269 if (is_array($LOCAL_LANG)) {
1270 if (!empty($LOCAL_LANG[$this->language])) {
1271 $LOCAL_LANG[$this->language] = t3lib_div::array_merge_recursive_overrule($LOCAL_LANG['default'],$LOCAL_LANG[$this->language]);
1272 } else {
1273 $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1274 }
1275 $JSLanguageArray .= 'HTMLArea.I18N["' . $plugin . '"] = ' . json_encode($LOCAL_LANG[$this->language]) . ';'. LF;
1276 }
1277 return $JSLanguageArray;
1278 }
1279
1280 /**
1281 * Return the JS code of the toolbar configuration for the HTMLArea editor
1282 *
1283 * @return string the JS code as nested JS arrays
1284 */
1285 protected function getJSToolbarArray() {
1286 // The toolbar array
1287 $toolbar = array();
1288 // The current row; a "linebreak" ends the current row
1289 $row = array();
1290 // The current group; each group is between "bar"s; a "linebreak" ends the current group
1291 $group = array();
1292 // Process each toolbar item in the toolbar order list
1293 foreach ($this->toolbarOrderArray as $item) {
1294 switch ($item) {
1295 case 'linebreak':
1296 // Add row to toolbar if not empty
1297 if (!empty($group)) {
1298 $row[] = $group;
1299 $group = array();
1300 }
1301 if (!empty($row)) {
1302 $toolbar[] = $row;
1303 $row = array();
1304 }
1305 break;
1306 case 'bar':
1307 // Add group to row if not empty
1308 if (!empty($group)) {
1309 $row[] = $group;
1310 $group = array();
1311 }
1312 break;
1313 case 'space':
1314 if (end($group) != $this->convertToolbarForHTMLArea($item)) {
1315 $group[] = $this->convertToolbarForHTMLArea($item);
1316 }
1317 break;
1318 default:
1319 if (in_array($item, $this->toolbar)) {
1320 // Add the item to the group
1321 $convertedItem = $this->convertToolbarForHTMLArea($item);
1322 if ($convertedItem) {
1323 $group[] = $convertedItem;
1324 }
1325 }
1326 break;
1327 }
1328 }
1329 // Add the last group and last line, if not empty
1330 if (!empty($group)) {
1331 $row[] = $group;
1332 }
1333 if (!empty($row)) {
1334 $toolbar[] = $row;
1335 }
1336 return json_encode($toolbar);
1337 }
1338
1339 public function getLLContent($string) {
1340 global $LANG;
1341
1342 $BE_lang = $LANG->lang;
1343 $BE_charSet = $LANG->charSet;
1344 $LANG->lang = $this->contentTypo3Language;
1345 $LANG->charSet = $this->contentCharset;
1346 $LLString = $LANG->JScharCode($LANG->sL($string));
1347 $LANG->lang = $BE_lang;
1348 $LANG->charSet = $BE_charSet;
1349 return $LLString;
1350 }
1351
1352 public function getPageConfigLabel($string,$JScharCode=1) {
1353 global $LANG, $TSFE, $TYPO3_CONF_VARS;
1354
1355 if ($this->is_FE()) {
1356 if (strcmp(substr($string,0,4),'LLL:') && $TYPO3_CONF_VARS['BE']['forceCharset']) {
1357 // A pure string coming from Page TSConfig must be in forceCharset, otherwise we just don't know..
1358 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $TYPO3_CONF_VARS['BE']['forceCharset'], $this->OutputCharset);
1359 } else {
1360 $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $this->charset, $this->OutputCharset);
1361 }
1362 $label = str_replace('"', '\"', str_replace('\\\'', '\'', $label));
1363 $label = $JScharCode ? $this->feJScharCode($label) : $label;
1364 } else {
1365 if (strcmp(substr($string,0,4),'LLL:')) {
1366 $label = $string;
1367 } else {
1368 $label = $LANG->sL(trim($string));
1369 }
1370 $label = str_replace('"', '\"', str_replace('\\\'', '\'', $label));
1371 $label = $JScharCode ? $LANG->JScharCode($label): $label;
1372 }
1373 return $label;
1374 }
1375
1376 function feJScharCode($str) {
1377 global $TSFE;
1378 // Convert string to UTF-8:
1379 if ($this->OutputCharset != 'utf-8') $str = $TSFE->csConvObj->utf8_encode($str,$this->OutputCharset);
1380 // Convert the UTF-8 string into a array of char numbers:
1381 $nArr = $TSFE->csConvObj->utf8_to_numberarray($str);
1382 return 'String.fromCharCode('.implode(',',$nArr).')';
1383 }
1384
1385 public function getFullFileName($filename) {
1386 if (substr($filename,0,4)=='EXT:') { // extension
1387 list($extKey,$local) = explode('/',substr($filename,4),2);
1388 $newFilename = '';
1389 if (strcmp($extKey,'') && t3lib_extMgm::isLoaded($extKey) && strcmp($local,'')) {
1390 $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? t3lib_extMgm::siteRelPath($extKey) : $this->backPath . t3lib_extMgm::extRelPath($extKey)) . $local;
1391 }
1392 } elseif (substr($filename,0,1) != '/') {
1393 $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? '' : ($this->backPath . '../')) . $filename;
1394 } else {
1395 $newFilename = (($this->is_FE() || $this->isFrontendEditActive()) ? '' : ($this->backPath . '../')) . substr($filename, 1);
1396 }
1397 return t3lib_div::resolveBackPath($newFilename);
1398 }
1399
1400 /**
1401 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1402 * This is for submit function of the form.
1403 *
1404 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1405 * @param string $formName: the name of the form
1406 * @param string $textareaId: the id of the textarea
1407 * @param string $textareaName: the name of the textarea
1408 *
1409 * @return string Javascript code
1410 */
1411 function setSaveRTE($RTEcounter, $formName, $textareaId, $textareaName) {
1412 return 'if (RTEarea["' . $textareaId . '"]) { document.' . $formName . '["' . $textareaName . '"].value = RTEarea["' . $textareaId . '"].editor.getHTML(); } else { OK = 0; };';
1413 }
1414
1415 /**
1416 * Return the Javascript code for copying the HTML code from the editor into the hidden input field.
1417 * This is for submit function of the form.
1418 *
1419 * @param integer $RTEcounter: The index number of the current RTE editing area within the form.
1420 * @param string $formName: the name of the form
1421 * @param string $textareaId: the id of the textarea
1422 *
1423 * @return string Javascript code
1424 */
1425 function setDeleteRTE($RTEcounter, $formName, $textareaId) {
1426 return 'if (RTEarea["' . $textareaId . '"]) { RTEarea["' . $textareaId . '"].deleted = true;}';
1427 }
1428
1429 /**
1430 * Return TRUE if we are in the FE, but not in the FE editing feature of BE.
1431 *
1432 * @return boolean
1433 */
1434
1435 function is_FE() {
1436 return is_object($GLOBALS['TSFE']) && !$this->isFrontendEditActive() && TYPO3_MODE=='FE';
1437 }
1438
1439 /**
1440 * Checks whether frontend editing is active.
1441 *
1442 * @return boolean
1443 */
1444 public function isFrontendEditActive() {
1445 return is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->beUserLogin && ($GLOBALS['BE_USER']->frontendEdit instanceof t3lib_frontendedit);
1446 }
1447 /**
1448 * Client Browser Information
1449 *
1450 * @param string $userAgent: The useragent string, t3lib_div::getIndpEnv('HTTP_USER_AGENT')
1451 * @return array Contains keys "useragent", "browser", "version", "system"
1452 * where "browser" is limited to the engines
1453 * and where "version" is a floating number
1454 */
1455 function clientInfo ($userAgent='') {
1456 if (!$userAgent) {
1457 $userAgent = t3lib_div::getIndpEnv('HTTP_USER_AGENT');
1458 }
1459 $browserInfo = t3lib_utility_Client::getBrowserInfo($userAgent);
1460 // Known engines: order is not irrelevant!
1461 $knownEngines = array('opera', 'msie', 'gecko', 'webkit');
1462 if (is_array($browserInfo['all'])) {
1463 foreach ($knownEngines as $engine) {
1464 if ($browserInfo['all'][$engine]) {
1465 $browserInfo['browser'] = $engine;
1466 $browserInfo['version'] = t3lib_utility_Client::getVersion($browserInfo['all'][$engine]);
1467 break;
1468 }
1469 }
1470 }
1471 return $browserInfo;
1472 }
1473 /**
1474 * Log usage of deprecated Page TS Config Property
1475 *
1476 * @param string $deprecatedProperty: Name of deprecated property
1477 * @param string $useProperty: Name of property to use instead
1478 * @param string $version: Version of TYPO3 in which the property will be removed
1479 *
1480 * @return void
1481 */
1482 public function logDeprecatedProperty ($deprecatedProperty, $useProperty, $version) {
1483 if (!$this->thisConfig['logDeprecatedProperties.']['disabled']) {
1484 $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);
1485 t3lib_div::deprecationLog($message);
1486 if (is_object($GLOBALS['BE_USER']) && $this->thisConfig['logDeprecatedProperties.']['logAlsoToBELog']) {
1487 $message = sprintf($GLOBALS['LANG']->getLL('deprecatedPropertyMessage'), $deprecatedProperty, $useProperty, $version, $this->thePid);
1488 $GLOBALS['BE_USER']->simplelog($message, $this->ID);
1489 }
1490 }
1491 }
1492 /***************************
1493 *
1494 * OTHER FUNCTIONS: (from Classic RTE)
1495 *
1496 ***************************/
1497 /**
1498 * @return [type] ...
1499 * @desc
1500 */
1501
1502 function RTEtsConfigParams() {
1503 if($this->is_FE()) {
1504 return '';
1505 } else {
1506 $p = t3lib_BEfunc::getSpecConfParametersFromArray($this->specConf['rte_transform']['parameters']);
1507 return $this->elementParts[0].':'.$this->elementParts[1].':'.$this->elementParts[2].':'.$this->thePid.':'.$this->typeVal.':'.$this->tscPID.':'.$p['imgpath'];
1508 }
1509 }
1510
1511 public function cleanList($str) {
1512 if (strstr($str,'*')) {
1513 $str = '*';
1514 } else {
1515 $str = implode(',',array_unique(t3lib_div::trimExplode(',',$str,1)));
1516 }
1517 return $str;
1518 }
1519
1520 function filterStyleEl($elValue,$matchList) {
1521 $matchParts = t3lib_div::trimExplode(',',$matchList,1);
1522 $styleParts = explode(';',$elValue);
1523 $nStyle=array();
1524 foreach ($styleParts as $k => $p) {
1525 $pp = t3lib_div::trimExplode(':',$p);
1526 if ($pp[0]&&$pp[1]) {
1527 foreach ($matchParts as $el) {
1528 $star=substr($el,-1)=='*';
1529 if (!strcmp($pp[0],$el) || ($star && t3lib_div::isFirstPartOfStr($pp[0],substr($el,0,-1)) )) {
1530 $nStyle[]=$pp[0].':'.$pp[1];
1531 } else unset($styleParts[$k]);
1532 }
1533 } else {
1534 unset($styleParts[$k]);
1535 }
1536 }
1537 return implode('; ',$nStyle);
1538 }
1539
1540 // Hook on lorem_ipsum extension to insert text into the RTE in wysiwyg mode
1541 function loremIpsumInsert($params) {
1542 return "
1543 if (typeof(lorem_ipsum) == 'function' && " . $params['element'] . ".tagName.toLowerCase() == 'textarea' ) lorem_ipsum(" . $params['element'] . ", lipsum_temp_strings[lipsum_temp_pointer]);
1544 ";
1545 }
1546 }
1547 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php'])) {
1548 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/rtehtmlarea/class.tx_rtehtmlarea_base.php']);
1549 }
1550 ?>