TYPO3 CMS  TYPO3_6-2
RteHtmlAreaBase.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Rtehtmlarea;
3 
20 
28 
29  // Configuration of supported browsers
33  public $conf_supported_browser = array(
34  'msie' => array(
35  array(
36  'version' => 6.0,
37  'system' => array(
38  'allowed' => array(
39  'winNT',
40  'win98',
41  'win95'
42  )
43  )
44  )
45  ),
46  'gecko' => array(
47  array(
48  'version' => 1.8
49  )
50  ),
51  'webkit' => array(
52  array(
53  'version' => 534
54  ),
55  array(
56  'version' => 523,
57  'system' => array(
58  'disallowed' => array(
59  'iOS',
60  'android'
61  )
62  )
63  )
64  ),
65  'opera' => array(
66  array(
67  'version' => 9.62,
68  'system' => array(
69  'disallowed' => array(
70  'iOS',
71  'android'
72  )
73  )
74  )
75  )
76  );
77 
78  // Always hide these toolbar buttons (TYPO3 button name)
82  public $conf_toolbar_hide = array(
83  'showhelp'
84  );
85 
86  // The order of the toolbar: the name is the TYPO3-button name
91 
92  // Conversion array: TYPO3 button names to htmlArea button names
97  'showhelp' => 'ShowHelp',
98  'space' => 'space',
99  'bar' => 'separator',
100  'linebreak' => 'linebreak'
101  );
102 
106  public $pluginButton = array();
107 
111  public $pluginLabel = array();
112 
113  // Alternative style for RTE <div> tag.
114  public $RTEdivStyle;
115 
116  // Relative path to this extension. It ends with "/"
117  public $extHttpPath;
118 
119  public $backPath = '';
120 
121  // TYPO3 site url
122  public $siteURL;
123 
124  // TYPO3 host url
125  public $hostURL;
126 
127  // Typo3 version
128  public $typoVersion;
129 
130  // Identifies the RTE as being the one from the "rtehtmlarea" extension if any external code needs to know
134  public $ID = 'rtehtmlarea';
135 
136  // If set, the content goes into a regular TEXT area field - for developing testing of transformations.
140  public $debugMode = FALSE;
141 
142  // For the editor
146  public $client;
147 
154  public $TCEform;
155 
159  public $elementId;
160 
165 
169  public $tscPID;
170 
174  public $typeVal;
175 
179  public $thePid;
180 
184  public $RTEsetup;
185 
189  public $thisConfig;
190 
194  public $confValues;
195 
196  public $language;
209  public $charset = 'utf-8';
210 
211  public $contentCharset = 'utf-8';
212 
213  public $OutputCharset = 'utf-8';
214 
218  public $editorCSS;
219 
223  public $specConf;
224 
228  public $toolbar = array();
229 
230  // Save the buttons for the toolbar
234  public $toolbarOrderArray = array();
235 
236  protected $pluginEnabledArray = array();
237 
238  // Array of plugin id's enabled in the current RTE editing area
239  protected $pluginEnabledCumulativeArray = array();
240 
241  // Cumulative array of plugin id's enabled so far in any of the RTE editing areas of the form
242  public $registeredPlugins = array();
243 
244  // Array of registered plugins indexed by their plugin Id's
245  protected $fullScreen = FALSE;
246  // Page renderer object
247  protected $pageRenderer;
248 
256  public function isAvailable() {
257  $this->client = $this->clientInfo();
258  $this->errorLog = array();
259  if (!$this->debugMode) {
260  // If debug-mode, let any browser through
261  $rteIsAvailable = FALSE;
262  $rteConfBrowser = $this->conf_supported_browser;
263  if (is_array($rteConfBrowser)) {
264  foreach ($rteConfBrowser as $browser => $browserConf) {
265  if ($browser == $this->client['browser']) {
266  // Config for Browser found, check it:
267  if (is_array($browserConf)) {
268  foreach ($browserConf as $browserConfSub) {
269  if ($browserConfSub['version'] <= $this->client['version'] || empty($browserConfSub['version'])) {
270  // Version is supported
271  if (is_array($browserConfSub['system'])) {
272  // Check against allowed systems
273  if (is_array($browserConfSub['system']['allowed'])) {
274  foreach ($browserConfSub['system']['allowed'] as $system) {
275  if (in_array($system, $this->client['all_systems'])) {
276  $rteIsAvailable = TRUE;
277  break;
278  }
279  }
280  } else {
281  // All allowed
282  $rteIsAvailable = TRUE;
283  }
284  // Check against disallowed systems
285  if (is_array($browserConfSub['system']['disallowed'])) {
286  foreach ($browserConfSub['system']['disallowed'] as $system) {
287  if (in_array($system, $this->client['all_systems'])) {
288  $rteIsAvailable = FALSE;
289  break;
290  }
291  }
292  }
293  } else {
294  // No system config: system is supported
295  $rteIsAvailable = TRUE;
296  break;
297  }
298  }
299  }
300  } else {
301  // no config for this browser found, so all versions or system with this browsers are allow
302  $rteIsAvailable = TRUE;
303  break;
304  }
305  }
306  }
307  } else {
308 
309  }
310  if (!$rteIsAvailable) {
311  $this->errorLog[] = 'RTE: Browser not supported.';
312  }
313  if (\TYPO3\CMS\Core\Utility\VersionNumberUtility::convertVersionNumberToInteger(TYPO3_version) < 4000000) {
314  $rteIsAvailable = FALSE;
315  $this->errorLog[] = 'rte: This version of htmlArea RTE cannot run under this version of TYPO3.';
316  }
317  }
318  return $rteIsAvailable;
319  }
320 
337  public function drawRTE($parentObject, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue) {
338  global $LANG, $TYPO3_DB;
339  $this->TCEform = $parentObject;
340  $inline = $this->TCEform->inline;
341  $LANG->includeLLFile('EXT:' . $this->ID . '/locallang.xml');
342  $this->client = $this->clientInfo();
344  $this->userUid = 'BE_' . $GLOBALS['BE_USER']->user['uid'];
345  // Draw form element:
346  if ($this->debugMode) {
347  // Draws regular text area (debug mode)
348  $item = parent::drawRTE($this->TCEform, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
349  } else {
350  // Draw real RTE
351  /* =======================================
352  * INIT THE EDITOR-SETTINGS
353  * =======================================
354  */
355  // Set backPath
356  $this->backPath = $this->TCEform->backPath;
357  // Get the path to this extension:
358  $this->extHttpPath = $this->backPath . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath($this->ID);
359  // Get the site URL
360  $this->siteURL = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
361  // Get the host URL
362  $this->hostURL = $this->siteURL . TYPO3_mainDir;
363  // Element ID + pid
364  $this->elementId = $PA['itemFormElName'];
365  // Form element name
366  $this->elementParts = explode('][', preg_replace('/\\]$/', '', preg_replace('/^(TSFE_EDIT\\[data\\]\\[|data\\[)/', '', $this->elementId)));
367  // Find the page PIDs:
368  list($this->tscPID, $this->thePid) = BackendUtility::getTSCpid(trim($this->elementParts[0]), trim($this->elementParts[1]), $thePidValue);
369  // Record "types" field value:
370  $this->typeVal = $RTEtypeVal;
371  // TCA "types" value for record
372  // Find "thisConfig" for record/editor:
373  unset($this->RTEsetup);
374  $this->RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', BackendUtility::getPagesTSconfig($this->tscPID));
375  $this->thisConfig = $thisConfig;
376  // Special configuration and default extras:
377  $this->specConf = $specConf;
378  if ($this->thisConfig['forceHTTPS']) {
379  $this->extHttpPath = preg_replace('/^(http|https)/', 'https', $this->extHttpPath);
380  $this->siteURL = preg_replace('/^(http|https)/', 'https', $this->siteURL);
381  $this->hostURL = preg_replace('/^(http|https)/', 'https', $this->hostURL);
382  }
383  // Register RTE windows
384  $this->TCEform->RTEwindows[] = $PA['itemFormElName'];
385  $textAreaId = preg_replace('/[^a-zA-Z0-9_:.-]/', '_', $PA['itemFormElName']);
386  $textAreaId = htmlspecialchars(preg_replace('/^[^a-zA-Z]/', 'x', $textAreaId));
387  /* =======================================
388  * LANGUAGES & CHARACTER SETS
389  * =======================================
390  */
391  // Languages: interface and content
392  $this->language = $GLOBALS['LANG']->lang;
393  if ($this->language === 'default' || !$this->language) {
394  $this->language = 'en';
395  }
396  $this->contentLanguageUid = max($row['sys_language_uid'], 0);
397  if ($this->contentLanguageUid) {
398  $this->contentISOLanguage = $this->language;
399  if (\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('static_info_tables')) {
400  $tableA = 'sys_language';
401  $tableB = 'static_languages';
402  $selectFields = $tableA . '.uid,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2';
403  $tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
404  $whereClause = $tableA . '.uid = ' . intval($this->contentLanguageUid);
405  $whereClause .= BackendUtility::BEenableFields($tableA);
406  $whereClause .= BackendUtility::deleteClause($tableA);
407  $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery($selectFields, $tableAB, $whereClause);
408  while ($languageRow = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
409  $this->contentISOLanguage = strtolower(trim($languageRow['lg_iso_2']) . (trim($languageRow['lg_country_iso_2']) ? '_' . trim($languageRow['lg_country_iso_2']) : ''));
410  }
411  }
412  } else {
413  $this->contentISOLanguage = trim($this->thisConfig['defaultContentLanguage']) ?: 'en';
414  $languageCodeParts = explode('_', $this->contentISOLanguage);
415  $this->contentISOLanguage = strtolower($languageCodeParts[0]) . ($languageCodeParts[1] ? '_' . strtoupper($languageCodeParts[1]) : '');
416  // Find the configured language in the list of localization locales
418  $locales = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\Locales');
419  // If not found, default to 'en'
420  if (!in_array($this->contentISOLanguage, $locales->getLocales())) {
421  $this->contentISOLanguage = 'en';
422  }
423  }
424  // Create content laguage service
425  $this->contentLanguageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Lang\\LanguageService');
426  $this->contentTypo3Language = $this->contentISOLanguage === 'en' ? 'default' : $this->contentISOLanguage;
427  $this->contentLanguageService->init($this->contentTypo3Language);
428  /* =======================================
429  * TOOLBAR CONFIGURATION
430  * =======================================
431  */
433  /* =======================================
434  * SET STYLES
435  * =======================================
436  */
437  // Check if wizard_rte called this for fullscreen edtition
438  if (GeneralUtility::_GP('M') === 'wizard_rte') {
439  $this->fullScreen = TRUE;
440  $RTEWidth = '100%';
441  $RTEHeight = '100%';
442  $RTEPaddingRight = '0';
443  $editorWrapWidth = '100%';
444  } else {
445  $options = $GLOBALS['BE_USER']->userTS['options.'];
446  $RTEWidth = 530 + (isset($options['RTELargeWidthIncrement']) ? (int)$options['RTELargeWidthIncrement'] : 150);
447  $RTEWidth -= $inline->getStructureDepth() > 0 ? ($inline->getStructureDepth() + 1) * $inline->getLevelMargin() : 0;
448  $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']);
449  if ($RTEWidthOverride) {
450  if (strstr($RTEWidthOverride, '%')) {
451  if ($this->client['browser'] != 'msie') {
452  $RTEWidth = (int)$RTEWidthOverride > 0 ? $RTEWidthOverride : '100%';
453  }
454  } else {
455  $RTEWidth = (int)$RTEWidthOverride > 0 ? (int)$RTEWidthOverride : $RTEWidth;
456  }
457  }
458  $RTEWidth = strstr($RTEWidth, '%') ? $RTEWidth : $RTEWidth . 'px';
459  $RTEHeight = 380 + (isset($options['RTELargeHeightIncrement']) ? (int)$options['RTELargeHeightIncrement'] : 0);
460  $RTEHeightOverride = is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteHeight']) && (int)$GLOBALS['BE_USER']->uc['rteHeight'] ? (int)$GLOBALS['BE_USER']->uc['rteHeight'] : (int)$this->thisConfig['RTEHeightOverride'];
461  $RTEHeight = $RTEHeightOverride > 0 ? $RTEHeightOverride : $RTEHeight;
462  $RTEPaddingRight = '2px';
463  $editorWrapWidth = '99%';
464  }
465  $editorWrapHeight = '100%';
466  $this->RTEdivStyle = 'position:relative; left:0px; top:0px; height:' . $RTEHeight . 'px; width:' . $RTEWidth . '; border: 1px solid black; padding: 2px ' . $RTEPaddingRight . ' 2px 2px;';
467  /* =======================================
468  * LOAD CSS AND JAVASCRIPT
469  * =======================================
470  */
471  $this->pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
472  // Preloading the pageStyle and including RTE skin stylesheets
473  $this->addPageStyle();
474  $this->addSkin();
475  // Register RTE in JS
476  $this->TCEform->additionalJS_post[] = $this->registerRTEinJS($this->TCEform->RTEcounter, $table, $row['uid'], $field, $textAreaId);
477  // Set the save option for the RTE
478  $this->TCEform->additionalJS_submit[] = $this->setSaveRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId, $PA['itemFormElName']);
479  $this->TCEform->additionalJS_delete[] = $this->setDeleteRTE($this->TCEform->RTEcounter, $this->TCEform->formName, $textAreaId);
480  // Loading ExtJs inline code
481  $this->pageRenderer->enableExtJSQuickTips();
482  // Add TYPO3 notifications JavaScript
483  $this->pageRenderer->addJsFile('sysext/backend/Resources/Public/JavaScript/notifications.js');
484  // Add RTE JavaScript
485  $this->addRteJsFiles($this->TCEform->RTEcounter);
486  $this->pageRenderer->addJsFile($this->buildJSMainLangFile($this->TCEform->RTEcounter));
487  $this->pageRenderer->addJsInlineCode('HTMLArea-init', $this->getRteInitJsCode(), TRUE);
488  /* =======================================
489  * DRAW THE EDITOR
490  * =======================================
491  */
492  // Transform value:
493  $value = $this->transformContent('rte', $PA['itemFormElValue'], $table, $field, $row, $specConf, $thisConfig, $RTErelPath, $thePidValue);
494  // Further content transformation by registered plugins
495  foreach ($this->registeredPlugins as $pluginId => $plugin) {
496  if ($this->isPluginEnabled($pluginId) && method_exists($plugin, 'transformContent')) {
497  $value = $plugin->transformContent($value);
498  }
499  }
500  // Draw the textarea
501  $visibility = 'hidden';
502  $item = $this->triggerField($PA['itemFormElName']) . '
503  <div id="pleasewait' . $textAreaId . '" class="pleasewait" style="display: block;" >' . $LANG->getLL('Please wait') . '</div>
504  <div id="editorWrap' . $textAreaId . '" class="editorWrap" style="visibility: hidden; width:' . $editorWrapWidth . '; height:' . $editorWrapHeight . ';">
505  <textarea id="RTEarea' . $textAreaId . '" name="' . htmlspecialchars($PA['itemFormElName']) . '" rows="0" cols="0" style="' . htmlspecialchars($this->RTEdivStyle, ENT_COMPAT, 'UTF-8', FALSE) . '">' . GeneralUtility::formatForTextarea($value) . '</textarea>
506  </div>' . LF;
507  }
508  // Return form item:
509  return $item;
510  }
511 
517  protected function addPageStyle() {
518  $this->addStyleSheet('rtehtmlarea-page-style', $this->getContentCssFileName(), 'htmlArea RTE Content CSS', 'alternate stylesheet');
519  }
520 
526  protected function getContentCssFileName() {
527  // Get stylesheet file name from Page TSConfig if any
528  $fileName = trim($this->thisConfig['contentCSS']);
529  $absolutePath = GeneralUtility::getFileAbsFileName($fileName);
530  // Fallback to default content css file if configured file does not exists or is of zero size
531  if (!$fileName || !file_exists($absolutePath) || !filesize($absolutePath)) {
532  $fileName = 'EXT:' . $this->ID . '/res/contentcss/default.css';
533  }
534  $fileName = $this->getFullFileName($fileName);
535  return $fileName;
536  }
537 
543  protected function addSkin() {
544  // Get skin file name from Page TSConfig if any
545  $skinFilename = trim($this->thisConfig['skin']) ?: 'EXT:' . $this->ID . '/htmlarea/skins/default/htmlarea.css';
546  $this->editorCSS = $this->getFullFileName($skinFilename);
547  $skinDir = dirname($this->editorCSS);
548  // Editing area style sheet
549  $this->editedContentCSS = $skinDir . '/htmlarea-edited-content.css';
550  $this->addStyleSheet('rtehtmlarea-editing-area-skin', $this->editedContentCSS);
551  // Main skin
552  $this->addStyleSheet('rtehtmlarea-skin', $this->editorCSS);
553  // Additional icons from registered plugins
554  foreach ($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] as $pluginId) {
555  if (is_object($this->registeredPlugins[$pluginId])) {
556  $pathToSkin = $this->registeredPlugins[$pluginId]->getPathToSkin();
557  if ($pathToSkin) {
558  $key = $this->registeredPlugins[$pluginId]->getExtensionKey();
559  $this->addStyleSheet('rtehtmlarea-plugin-' . $pluginId . '-skin', ($this->is_FE() ? \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath($key) : $this->backPath . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath($key)) . $pathToSkin);
560  }
561  }
562  }
563  }
564 
574  protected function addStyleSheet($key, $href, $title = '', $relation = 'stylesheet') {
575  // 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
576  if (is_object($this->TCEform->inline) && $this->TCEform->inline->isAjaxCall) {
577  $this->TCEform->additionalCode_pre[$key] = '<link rel="' . $relation . '" type="text/css" href="' . $href . '" title="' . $title . '" />';
578  } else {
579  $this->pageRenderer->addCssFile($href, $relation, 'screen', $title);
580  }
581  }
582 
588  protected function initializeToolbarConfiguration() {
589  // Enable registred plugins
590  $this->enableRegisteredPlugins();
591  // Configure toolbar
592  $this->setToolbar();
593  // Check if some plugins need to be disabled
594  $this->setPlugins();
595  // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
596  $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = $this->pluginEnabledArray;
597  if ($this->TCEform->RTEcounter > 1 && isset($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter - 1]) && is_array($this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter - 1])) {
598  $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter] = array_unique(array_values(array_merge($this->pluginEnabledArray, $this->pluginEnabledCumulativeArray[$this->TCEform->RTEcounter - 1])));
599  }
600  }
601 
607  public function enableRegisteredPlugins() {
608  global $TYPO3_CONF_VARS;
609  // Traverse registered plugins
610  if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'])) {
611  foreach ($TYPO3_CONF_VARS['EXTCONF'][$this->ID]['plugins'] as $pluginId => $pluginObjectConfiguration) {
612  $plugin = FALSE;
613  if (is_array($pluginObjectConfiguration) && count($pluginObjectConfiguration)) {
614  $plugin = GeneralUtility::getUserObj($pluginObjectConfiguration['objectReference']);
615  }
616  if (is_object($plugin)) {
617  if ($plugin->main($this)) {
618  $this->registeredPlugins[$pluginId] = $plugin;
619  // Override buttons from previously registered plugins
620  $pluginButtons = GeneralUtility::trimExplode(',', $plugin->getPluginButtons(), TRUE);
621  foreach ($this->pluginButton as $previousPluginId => $buttonList) {
622  $this->pluginButton[$previousPluginId] = implode(',', array_diff(GeneralUtility::trimExplode(',', $this->pluginButton[$previousPluginId], TRUE), $pluginButtons));
623  }
624  $this->pluginButton[$pluginId] = $plugin->getPluginButtons();
625  $pluginLabels = GeneralUtility::trimExplode(',', $plugin->getPluginLabels(), TRUE);
626  foreach ($this->pluginLabel as $previousPluginId => $labelList) {
627  $this->pluginLabel[$previousPluginId] = implode(',', array_diff(GeneralUtility::trimExplode(',', $this->pluginLabel[$previousPluginId], TRUE), $pluginLabels));
628  }
629  $this->pluginLabel[$pluginId] = $plugin->getPluginLabels();
630  $this->pluginEnabledArray[] = $pluginId;
631  }
632  }
633  }
634  }
635  // Process overrides
636  $hidePlugins = array();
637  foreach ($this->registeredPlugins as $pluginId => $plugin) {
638  if ($plugin->addsButtons() && !$this->pluginButton[$pluginId]) {
639  $hidePlugins[] = $pluginId;
640  }
641  }
642  $this->pluginEnabledArray = array_unique(array_diff($this->pluginEnabledArray, $hidePlugins));
643  }
644 
650  public function setToolbar() {
651  if ($this->client['browser'] == 'msie' || $this->client['browser'] == 'opera') {
652  $this->thisConfig['keepButtonGroupTogether'] = 0;
653  }
654  $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, space, textstylelabel, textstyle, linebreak,
655  bar, formattext, bold, strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code, definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
656  bar, fontstyle, space, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, line,
657  bar, left, center, right, justifyfull,
658  bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent, bar, lefttoright, righttoleft, language, showlanguagemarks,
659  bar, textcolor, bgcolor, textindicator,
660  bar, editelement, showmicrodata, 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,
661  bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pastetoggle, pastebehaviour, bar, undo, redo, bar, showhelp, about, linebreak,
662  ' . ($this->thisConfig['hideTableOperationsInToolbar'] ? '' : 'bar, toggleborders,') . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
663  columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
664  cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
665  // Additional buttons from registered plugins
666  foreach ($this->registeredPlugins as $pluginId => $plugin) {
667  if ($this->isPluginEnabled($pluginId)) {
668  $this->defaultToolbarOrder = $plugin->addButtonsToToolbar();
669  }
670  }
671  $toolbarOrder = $this->thisConfig['toolbarOrder'] ?: $this->defaultToolbarOrder;
672  // Getting rid of undefined buttons
673  $this->toolbarOrderArray = array_intersect(GeneralUtility::trimExplode(',', $toolbarOrder, TRUE), GeneralUtility::trimExplode(',', $this->defaultToolbarOrder, TRUE));
674  $toolbarOrder = array_unique(array_values($this->toolbarOrderArray));
675  // Fetching specConf for field from backend
676  $pList = is_array($this->specConf['richtext']['parameters']) ? implode(',', $this->specConf['richtext']['parameters']) : '';
677  if ($pList != '*') {
678  // If not all
679  $show = is_array($this->specConf['richtext']['parameters']) ? $this->specConf['richtext']['parameters'] : array();
680  if ($this->thisConfig['showButtons']) {
681  if (!GeneralUtility::inList($this->thisConfig['showButtons'], '*')) {
682  $show = array_unique(array_merge($show, GeneralUtility::trimExplode(',', $this->thisConfig['showButtons'], TRUE)));
683  } else {
684  $show = array_unique(array_merge($show, $toolbarOrder));
685  }
686  }
687  if (is_array($this->thisConfig['showButtons.'])) {
688  foreach ($this->thisConfig['showButtons.'] as $buttonId => $value) {
689  if ($value) {
690  $show[] = $buttonId;
691  }
692  }
693  $show = array_unique($show);
694  }
695  } else {
696  $show = $toolbarOrder;
697  }
698  // Resticting to RTEkeyList for backend user
699  if (is_object($GLOBALS['BE_USER'])) {
700  $RTEkeyList = isset($GLOBALS['BE_USER']->userTS['options.']['RTEkeyList']) ? $GLOBALS['BE_USER']->userTS['options.']['RTEkeyList'] : '*';
701  if ($RTEkeyList != '*') {
702  // If not all
703  $show = array_intersect($show, GeneralUtility::trimExplode(',', $RTEkeyList, TRUE));
704  }
705  }
706  // Hiding buttons of disabled plugins
707  $hideButtons = array('space', 'bar', 'linebreak');
708  foreach ($this->pluginButton as $pluginId => $buttonList) {
709  if (!$this->isPluginEnabled($pluginId)) {
710  $buttonArray = GeneralUtility::trimExplode(',', $buttonList, TRUE);
711  foreach ($buttonArray as $button) {
712  $hideButtons[] = $button;
713  }
714  }
715  }
716  // Hiding labels of disabled plugins
717  foreach ($this->pluginLabel as $pluginId => $label) {
718  if (!$this->isPluginEnabled($pluginId)) {
719  $hideButtons[] = $label;
720  }
721  }
722  // Hiding buttons
723  $show = array_diff($show, $this->conf_toolbar_hide, GeneralUtility::trimExplode(',', $this->thisConfig['hideButtons'], TRUE));
724  // Apply toolbar constraints from registered plugins
725  foreach ($this->registeredPlugins as $pluginId => $plugin) {
726  if ($this->isPluginEnabled($pluginId) && method_exists($plugin, 'applyToolbarConstraints')) {
727  $show = $plugin->applyToolbarConstraints($show);
728  }
729  }
730  // Getting rid of the buttons for which we have no position
731  $show = array_intersect($show, $toolbarOrder);
732  $this->toolbar = $show;
733  }
734 
740  public function setPlugins() {
741  // Disabling a plugin that adds buttons if none of its buttons is in the toolbar
742  $hidePlugins = array();
743  foreach ($this->pluginButton as $pluginId => $buttonList) {
744  if ($this->registeredPlugins[$pluginId]->addsButtons()) {
745  $showPlugin = FALSE;
746  $buttonArray = GeneralUtility::trimExplode(',', $buttonList, TRUE);
747  foreach ($buttonArray as $button) {
748  if (in_array($button, $this->toolbar)) {
749  $showPlugin = TRUE;
750  }
751  }
752  if (!$showPlugin) {
753  $hidePlugins[] = $pluginId;
754  }
755  }
756  }
757  $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
758  // Hiding labels of disabled plugins
759  $hideLabels = array();
760  foreach ($this->pluginLabel as $pluginId => $label) {
761  if (!$this->isPluginEnabled($pluginId)) {
762  $hideLabels[] = $label;
763  }
764  }
765  $this->toolbar = array_diff($this->toolbar, $hideLabels);
766  // Adding plugins declared as prerequisites by enabled plugins
767  $requiredPlugins = array();
768  foreach ($this->registeredPlugins as $pluginId => $plugin) {
769  if ($this->isPluginEnabled($pluginId)) {
770  $requiredPlugins = array_merge($requiredPlugins, GeneralUtility::trimExplode(',', $plugin->getRequiredPlugins(), TRUE));
771  }
772  }
773  $requiredPlugins = array_unique($requiredPlugins);
774  foreach ($requiredPlugins as $pluginId) {
775  if (is_object($this->registeredPlugins[$pluginId]) && !$this->isPluginEnabled($pluginId)) {
776  $this->pluginEnabledArray[] = $pluginId;
777  }
778  }
779  $this->pluginEnabledArray = array_unique($this->pluginEnabledArray);
780  // Completing the toolbar conversion array for htmlArea
781  foreach ($this->registeredPlugins as $pluginId => $plugin) {
782  if ($this->isPluginEnabled($pluginId)) {
783  $this->convertToolbarForHtmlAreaArray = array_unique(array_merge($this->convertToolbarForHtmlAreaArray, $plugin->getConvertToolbarForHtmlAreaArray()));
784  }
785  }
786  }
787 
795  public function convertToolbarForHTMLArea($button) {
796  return $this->convertToolbarForHtmlAreaArray[$button];
797  }
798 
805  protected function addRteJsFiles($RTEcounter) {
806  $this->pageRenderer->addJsFile($this->getFullFileName('EXT:' . $this->ID . '/htmlarea/htmlarea.js'));
807  foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
808  $extensionKey = is_object($this->registeredPlugins[$pluginId]) ? $this->registeredPlugins[$pluginId]->getExtensionKey() : $this->ID;
809  $this->pageRenderer->addJsFile($this->getFullFileName('EXT:' . $extensionKey . '/htmlarea/plugins/' . $pluginId . '/' . strtolower(preg_replace('/([a-z])([A-Z])([a-z])/', '$1-$2$3', $pluginId)) . '.js'));
810  }
811  }
812 
818  protected function getRteInitJsCode() {
819  return '
820  if (typeof(RTEarea) == "undefined") {
821  RTEarea = new Object();
822  RTEarea[0] = new Object();
823  RTEarea[0].version = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF'][$this->ID]['version'] . '";
824  RTEarea[0].editorUrl = "' . $this->extHttpPath . 'htmlarea/";
825  RTEarea[0].editorCSS = "' . GeneralUtility::createVersionNumberedFilename($this->editorCSS) . '";
826  RTEarea[0].editorSkin = "' . dirname($this->editorCSS) . '/";
827  RTEarea[0].editedContentCSS = "' . GeneralUtility::createVersionNumberedFilename($this->editedContentCSS) . '";
828  RTEarea[0].hostUrl = "' . $this->hostURL . '";
829  RTEarea.init = function() {
830  if (typeof(HTMLArea) == "undefined" || !Ext.isReady) {
831  window.setTimeout("RTEarea.init();", 10);
832  } else {
833  Ext.QuickTips.init();
834  HTMLArea.init();
835  }
836  };
837  RTEarea.initEditor = function(editorNumber) {
838  if (typeof(HTMLArea) == "undefined" || !HTMLArea.isReady) {
839  RTEarea.initEditor.defer(40, null, [editorNumber]);
840  } else {
841  HTMLArea.initEditor(editorNumber);
842  }
843  };
844  }
845  RTEarea.init();';
846  }
847 
859  public function registerRTEinJS($RTEcounter, $table = '', $uid = '', $field = '', $textAreaId = '') {
860  $configureRTEInJavascriptString = '
861  if (typeof(configureEditorInstance) == "undefined") {
862  configureEditorInstance = new Object();
863  }
864  configureEditorInstance["' . $textAreaId . '"] = function() {
865  if (typeof(RTEarea) == "undefined" || typeof(HTMLArea) == "undefined") {
866  window.setTimeout("configureEditorInstance[\'' . $textAreaId . '\']();", 40);
867  } else {
868  editornumber = "' . $textAreaId . '";
869  RTEarea[editornumber] = new Object();
870  RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";
871  RTEarea[editornumber].number = editornumber;
872  RTEarea[editornumber].deleted = false;
873  RTEarea[editornumber].textAreaId = "' . $textAreaId . '";
874  RTEarea[editornumber].id = "RTEarea" + editornumber;
875  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'])) . '";
876  RTEarea[editornumber].RTEHeightOverride = "' . (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteHeight']) && (int)$GLOBALS['BE_USER']->uc['rteHeight'] ? (int)$GLOBALS['BE_USER']->uc['rteHeight'] : (int)$this->thisConfig['RTEHeightOverride']) . '";
877  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')) . ';
878  RTEarea[editornumber].maxHeight = "' . (is_object($GLOBALS['BE_USER']) && isset($GLOBALS['BE_USER']->uc['rteMaxHeight']) && (int)$GLOBALS['BE_USER']->uc['rteMaxHeight'] ? trim($GLOBALS['BE_USER']->uc['rteMaxHeight']) : ((int)$this->thisConfig['rteMaxHeight'] ?: '2000')) . '";
879  RTEarea[editornumber].fullScreen = ' . ($this->fullScreen ? 'true' : 'false') . ';
880  RTEarea[editornumber].showStatusBar = ' . (trim($this->thisConfig['showStatusBar']) ? 'true' : 'false') . ';
881  RTEarea[editornumber].enableWordClean = ' . (trim($this->thisConfig['enableWordClean']) ? 'true' : 'false') . ';
882  RTEarea[editornumber].htmlRemoveComments = ' . (trim($this->thisConfig['removeComments']) ? 'true' : 'false') . ';
883  RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->thisConfig['disableEnterParagraphs']) ? 'true' : 'false') . ';
884  RTEarea[editornumber].disableObjectResizing = ' . (trim($this->thisConfig['disableObjectResizing']) ? 'true' : 'false') . ';
885  RTEarea[editornumber].removeTrailingBR = ' . (trim($this->thisConfig['removeTrailingBR']) ? 'true' : 'false') . ';
886  RTEarea[editornumber].useCSS = ' . (trim($this->thisConfig['useCSS']) ? 'true' : 'false') . ';
887  RTEarea[editornumber].keepButtonGroupTogether = ' . (trim($this->thisConfig['keepButtonGroupTogether']) ? 'true' : 'false') . ';
888  RTEarea[editornumber].disablePCexamples = ' . (trim($this->thisConfig['disablePCexamples']) ? 'true' : 'false') . ';
889  RTEarea[editornumber].showTagFreeClasses = ' . (trim($this->thisConfig['showTagFreeClasses']) ? 'true' : 'false') . ';
890  RTEarea[editornumber].useHTTPS = ' . (trim(stristr($this->siteURL, 'https')) || $this->thisConfig['forceHTTPS'] ? 'true' : 'false') . ';
891  RTEarea[editornumber].tceformsNested = ' . (is_object($this->TCEform) && method_exists($this->TCEform, 'getDynNestedStack') ? $this->TCEform->getDynNestedStack(TRUE) : '[]') . ';
892  RTEarea[editornumber].dialogueWindows = new Object();';
893  if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromTop'])) {
894  $configureRTEInJavascriptString .= '
895  RTEarea[editornumber].dialogueWindows.positionFromTop = ' . (int)$this->thisConfig['dialogueWindows.']['defaultPositionFromTop'] . ';';
896  }
897  if (isset($this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'])) {
898  $configureRTEInJavascriptString .= '
899  RTEarea[editornumber].dialogueWindows.positionFromLeft = ' . (int)$this->thisConfig['dialogueWindows.']['defaultPositionFromLeft'] . ';';
900  }
901  // The following properties apply only to the backend
902  if (!$this->is_FE()) {
903  $configureRTEInJavascriptString .= '
904  RTEarea[editornumber].sys_language_content = "' . $this->contentLanguageUid . '";
905  RTEarea[editornumber].typo3ContentLanguage = "' . $this->contentTypo3Language . '";
906  RTEarea[editornumber].typo3ContentCharset = "' . $this->contentCharset . '";
907  RTEarea[editornumber].userUid = "' . $this->userUid . '";';
908  }
909  // Setting the plugin flags
910  $configureRTEInJavascriptString .= '
911  RTEarea[editornumber].plugin = new Object();
912  RTEarea[editornumber].pathToPluginDirectory = new Object();';
913  foreach ($this->pluginEnabledArray as $pluginId) {
914  $configureRTEInJavascriptString .= '
915  RTEarea[editornumber].plugin.' . $pluginId . ' = true;';
916  if (is_object($this->registeredPlugins[$pluginId])) {
917  $pathToPluginDirectory = $this->registeredPlugins[$pluginId]->getPathToPluginDirectory();
918  if ($pathToPluginDirectory) {
919  $configureRTEInJavascriptString .= '
920  RTEarea[editornumber].pathToPluginDirectory.' . $pluginId . ' = "' . $pathToPluginDirectory . '";';
921  }
922  }
923  }
924  // Setting the buttons configuration
925  $configureRTEInJavascriptString .= '
926  RTEarea[editornumber].buttons = new Object();';
927  if (is_array($this->thisConfig['buttons.'])) {
928  foreach ($this->thisConfig['buttons.'] as $buttonIndex => $conf) {
929  $button = substr($buttonIndex, 0, -1);
930  if (is_array($conf)) {
931  $configureRTEInJavascriptString .= '
932  RTEarea[editornumber].buttons.' . $button . ' = ' . $this->buildNestedJSArray($conf) . ';';
933  }
934  }
935  }
936  // Setting the list of tags to be removed if specified in the RTE config
937  if (trim($this->thisConfig['removeTags'])) {
938  $configureRTEInJavascriptString .= '
939  RTEarea[editornumber].htmlRemoveTags = /^(' . implode('|', GeneralUtility::trimExplode(',', $this->thisConfig['removeTags'], TRUE)) . ')$/i;';
940  }
941  // Setting the list of tags to be removed with their contents if specified in the RTE config
942  if (trim($this->thisConfig['removeTagsAndContents'])) {
943  $configureRTEInJavascriptString .= '
944  RTEarea[editornumber].htmlRemoveTagsAndContents = /^(' . implode('|', GeneralUtility::trimExplode(',', $this->thisConfig['removeTagsAndContents'], TRUE)) . ')$/i;';
945  }
946  // Setting array of custom tags if specified in the RTE config
947  if (!empty($this->thisConfig['customTags'])) {
948  $customTags = GeneralUtility::trimExplode(',', $this->thisConfig['customTags'], TRUE);
949  if (!empty($customTags)) {
950  $configureRTEInJavascriptString .= '
951  RTEarea[editornumber].customTags= ' . json_encode($customTags) . ';';
952  }
953  }
954  // Setting the pageStyle
955  $configureRTEInJavascriptString .= '
956  RTEarea[editornumber].pageStyle = "' . GeneralUtility::createVersionNumberedFilename($this->getContentCssFileName()) . '";';
957  // Process classes configuration
958  $classesConfigurationRequired = FALSE;
959  foreach ($this->registeredPlugins as $pluginId => $plugin) {
960  if ($this->isPluginEnabled($pluginId)) {
961  $classesConfigurationRequired = $classesConfigurationRequired || $plugin->requiresClassesConfiguration();
962  }
963  }
964  if ($classesConfigurationRequired) {
965  $configureRTEInJavascriptString .= $this->buildJSClassesConfig($RTEcounter);
966  }
967  // Add Javascript configuration for registered plugins
968  foreach ($this->registeredPlugins as $pluginId => $plugin) {
969  if ($this->isPluginEnabled($pluginId)) {
970  $configureRTEInJavascriptString .= $plugin->buildJavascriptConfiguration('editornumber');
971  }
972  }
973  // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
974  $configureRTEInJavascriptString .= '
975  RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';
976  RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';
977  RTEarea.initEditor(editornumber);
978  }
979  };
980  configureEditorInstance["' . $textAreaId . '"]();';
981  return $configureRTEInJavascriptString;
982  }
983 
991  public function isPluginEnabled($pluginId) {
992  return in_array($pluginId, $this->pluginEnabledArray);
993  }
994 
1002  public function buildStyleSheet() {
1003  $stylesheet = '/* mainStyleOverride and inlineStyle properties ignored. */';
1004  return $stylesheet;
1005  }
1006 
1014  public function buildJSClassesConfig($RTEcounter) {
1015  // Include JS arrays of configured classes
1016  $configureRTEInJavascriptString .= '
1017  RTEarea[editornumber].classesUrl = "' . ($this->is_FE() && $GLOBALS['TSFE']->absRefPrefix ? $GLOBALS['TSFE']->absRefPrefix : '') . $this->writeTemporaryFile('', ('classes_' . $this->language), 'js', $this->buildJSClassesArray(), TRUE) . '";';
1018  return $configureRTEInJavascriptString;
1019  }
1020 
1027  public function buildJSClassesArray() {
1028  if ($this->is_FE()) {
1029  $RTEProperties = $this->RTEsetup;
1030  } else {
1031  $RTEProperties = $this->RTEsetup['properties'];
1032  }
1033  $classesArray = array('labels' => array(), 'values' => array(), 'noShow' => array(), 'alternating' => array(), 'counting' => array(), 'XOR' => array());
1034  $JSClassesArray = '';
1035  // Scanning the list of classes if specified in the RTE config
1036  if (is_array($RTEProperties['classes.'])) {
1037  foreach ($RTEProperties['classes.'] as $className => $conf) {
1038  $className = rtrim($className, '.');
1039  $label = '';
1040  if (!empty($conf['name'])) {
1041  $label = $this->getPageConfigLabel($conf['name'], FALSE);
1042  }
1043  $classesArray['labels'][$className] = $label;
1044  $classesArray['values'][$className] = str_replace('\\\'', '\'', $conf['value']);
1045  if (isset($conf['noShow'])) {
1046  $classesArray['noShow'][$className] = $conf['noShow'];
1047  }
1048  if (is_array($conf['alternating.'])) {
1049  $classesArray['alternating'][$className] = $conf['alternating.'];
1050  }
1051  if (is_array($conf['counting.'])) {
1052  $classesArray['counting'][$className] = $conf['counting.'];
1053  }
1054  }
1055  }
1056  // Scanning the list of sets of mutually exclusives classes if specified in the RTE config
1057  if (is_array($RTEProperties['mutuallyExclusiveClasses.'])) {
1058  foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
1059  $classSet = GeneralUtility::trimExplode(',', $conf, TRUE);
1060  $classList = implode(',', $classSet);
1061  foreach ($classSet as $className) {
1062  $classesArray['XOR'][$className] = '/^(' . implode('|', GeneralUtility::trimExplode(',', GeneralUtility::rmFromList($className, $classList), TRUE)) . ')$/';
1063  }
1064  }
1065  }
1066  foreach ($classesArray as $key => $subArray) {
1067  $JSClassesArray .= 'HTMLArea.classes' . ucfirst($key) . ' = ' . $this->buildNestedJSArray($subArray) . ';' . LF;
1068  }
1069  return $JSClassesArray;
1070  }
1071 
1082  public function buildNestedJSArray($conf) {
1083  $convertedConf = GeneralUtility::removeDotsFromTS($conf);
1084  return str_replace(array(':"0"', ':"\\/^(', ')$\\/i"', ':"\\/^(', ')$\\/"', '[]'), array(':false', ':/^(', ')$/i', ':/^(', ')$/', '{}'), json_encode($convertedConf));
1085  }
1086 
1093  public function buildJSMainLangArray() {
1094  $JSLanguageArray = 'HTMLArea.I18N = new Object();' . LF;
1095  $labelsArray = array('tooltips' => array(), 'msg' => array(), 'dialogs' => array());
1096  foreach ($labelsArray as $labels => $subArray) {
1097  $LOCAL_LANG = GeneralUtility::readLLfile('EXT:' . $this->ID . '/htmlarea/locallang_' . $labels . '.xlf', $this->language, 'utf-8');
1098  if (!empty($LOCAL_LANG[$this->language])) {
1099  $mergedLocalLang = $LOCAL_LANG['default'];
1100  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($mergedLocalLang, $LOCAL_LANG[$this->language], TRUE, FALSE);
1101  $LOCAL_LANG[$this->language] = $mergedLocalLang;
1102  } else {
1103  $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1104  }
1105  $labelsArray[$labels] = $LOCAL_LANG[$this->language];
1106  }
1107  $JSLanguageArray .= 'HTMLArea.I18N = ' . json_encode($labelsArray) . ';' . LF;
1108  return $JSLanguageArray;
1109  }
1110 
1121  public function writeTemporaryFile($sourceFileName = '', $label, $fileExtension = 'js', $contents = '', $concatenate = FALSE) {
1122  if ($sourceFileName) {
1123  $output = '';
1124  $source = GeneralUtility::getFileAbsFileName($sourceFileName);
1125  $output = file_get_contents($source);
1126  } else {
1127  $output = $contents;
1128  }
1129  $relativeFilename = 'typo3temp/' . $this->ID . '_' . str_replace('-', '_', $label) . '_' . GeneralUtility::shortMD5((TYPO3_version . $TYPO3_CONF_VARS['EXTCONF'][$this->ID]['version'] . ($sourceFileName ? $sourceFileName : $output)), 20) . '.' . $fileExtension;
1130  $destination = PATH_site . $relativeFilename;
1131  if (!file_exists($destination)) {
1132  $minifiedJavaScript = '';
1133  if ($fileExtension == 'js' && $output != '') {
1134  $minifiedJavaScript = GeneralUtility::minifyJavaScript($output);
1135  }
1136  $failure = GeneralUtility::writeFileToTypo3tempDir($destination, $minifiedJavaScript ? $minifiedJavaScript : $output);
1137  if ($failure) {
1138  throw new \RuntimeException($failure, 1294585668);
1139  }
1140  }
1141  if ($this->is_FE()) {
1142  $filename = $relativeFilename;
1143  } else {
1144  $filename = ($this->isFrontendEditActive() ? '' : $this->backPath . '../') . $relativeFilename;
1145  }
1146  return GeneralUtility::resolveBackPath($filename);
1147  }
1148 
1156  public function buildJSMainLangFile($RTEcounter) {
1157  $contents = $this->buildJSMainLangArray() . LF;
1158  foreach ($this->pluginEnabledCumulativeArray[$RTEcounter] as $pluginId) {
1159  $contents .= $this->buildJSLangArray($pluginId) . LF;
1160  }
1161  return $this->writeTemporaryFile('', $this->language . '_' . $this->OutputCharset, 'js', $contents, TRUE);
1162  }
1163 
1171  public function buildJSLangArray($plugin) {
1172  $extensionKey = is_object($this->registeredPlugins[$plugin]) ? $this->registeredPlugins[$plugin]->getExtensionKey() : $this->ID;
1173  $LOCAL_LANG = GeneralUtility::readLLfile('EXT:' . $extensionKey . '/htmlarea/plugins/' . $plugin . '/locallang.xlf', $this->language, 'utf-8', 1);
1174  $JSLanguageArray = 'HTMLArea.I18N["' . $plugin . '"] = new Object();' . LF;
1175  if (is_array($LOCAL_LANG)) {
1176  if (!empty($LOCAL_LANG[$this->language])) {
1177  $defaultLocalLang = $LOCAL_LANG['default'];
1178  \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($defaultLocalLang, $LOCAL_LANG[$this->language], TRUE, FALSE);
1179  $LOCAL_LANG[$this->language] = $defaultLocalLang;
1180  } else {
1181  $LOCAL_LANG[$this->language] = $LOCAL_LANG['default'];
1182  }
1183  $JSLanguageArray .= 'HTMLArea.I18N["' . $plugin . '"] = ' . json_encode($LOCAL_LANG[$this->language]) . ';' . LF;
1184  }
1185  return $JSLanguageArray;
1186  }
1187 
1193  protected function getJSToolbarArray() {
1194  // The toolbar array
1195  $toolbar = array();
1196  // The current row; a "linebreak" ends the current row
1197  $row = array();
1198  // The current group; each group is between "bar"s; a "linebreak" ends the current group
1199  $group = array();
1200  // Process each toolbar item in the toolbar order list
1201  foreach ($this->toolbarOrderArray as $item) {
1202  switch ($item) {
1203  case 'linebreak':
1204  // Add row to toolbar if not empty
1205  if (!empty($group)) {
1206  $row[] = $group;
1207  $group = array();
1208  }
1209  if (!empty($row)) {
1210  $toolbar[] = $row;
1211  $row = array();
1212  }
1213  break;
1214  case 'bar':
1215  // Add group to row if not empty
1216  if (!empty($group)) {
1217  $row[] = $group;
1218  $group = array();
1219  }
1220  break;
1221  case 'space':
1222  if (end($group) != $this->convertToolbarForHTMLArea($item)) {
1223  $group[] = $this->convertToolbarForHTMLArea($item);
1224  }
1225  break;
1226  default:
1227  if (in_array($item, $this->toolbar)) {
1228  // Add the item to the group
1229  $convertedItem = $this->convertToolbarForHTMLArea($item);
1230  if ($convertedItem) {
1231  $group[] = $convertedItem;
1232  }
1233  }
1234  }
1235  }
1236  // Add the last group and last line, if not empty
1237  if (!empty($group)) {
1238  $row[] = $group;
1239  }
1240  if (!empty($row)) {
1241  $toolbar[] = $row;
1242  }
1243  return json_encode($toolbar);
1244  }
1245 
1252  public function getLLContent($string) {
1253  return GeneralUtility::quoteJSvalue($this->contentLanguageService->sL($string));
1254  }
1255 
1256  public function getPageConfigLabel($string, $JScharCode = 1) {
1257  global $LANG, $TSFE, $TYPO3_CONF_VARS;
1258  if ($this->is_FE()) {
1259  if (substr($string, 0, 4) !== 'LLL:') {
1260  // A pure string coming from Page TSConfig must be in utf-8
1261  $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), 'utf-8', $this->OutputCharset);
1262  } else {
1263  $label = $TSFE->csConvObj->conv($TSFE->sL(trim($string)), $this->charset, $this->OutputCharset);
1264  }
1265  $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
1266  $label = $JScharCode ? $this->feJScharCode($label) : $label;
1267  } else {
1268  if (substr($string, 0, 4) !== 'LLL:') {
1269  $label = $string;
1270  } else {
1271  $label = $LANG->sL(trim($string));
1272  }
1273  $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
1274  $label = $JScharCode ? GeneralUtility::quoteJSvalue($label) : $label;
1275  }
1276  return $label;
1277  }
1278 
1282  public function feJScharCode($str) {
1283  // Convert string to UTF-8:
1284  if ($this->OutputCharset != 'utf-8') {
1285  $str = $GLOBALS['TSFE']->csConvObj->utf8_encode($str, $this->OutputCharset);
1286  }
1287  // Convert the UTF-8 string into a 'JavaScript-safe' encoded string:
1288  return GeneralUtility::quoteJSvalue($str);
1289  }
1290 
1297  public function getFullFileName($filename) {
1298  if (substr($filename, 0, 4) == 'EXT:') {
1299  // extension
1300  list($extKey, $local) = explode('/', substr($filename, 4), 2);
1301  $newFilename = '';
1302  if ((string)$extKey !== '' && \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extKey) && (string)$local !== '') {
1303  $newFilename = ($this->is_FE() || $this->isFrontendEditActive() ? \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::siteRelPath($extKey) : $this->backPath . \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extRelPath($extKey)) . $local;
1304  }
1305  } else {
1306  $path = ($this->is_FE() || $this->isFrontendEditActive() ? '' : $this->backPath . '../');
1307  $newFilename = $path . ($filename[0] === '/' ? substr($filename, 1) : $filename);
1308  }
1309  return GeneralUtility::resolveBackPath($newFilename);
1310  }
1311 
1323  public function setSaveRTE($RTEcounter, $formName, $textareaId, $textareaName) {
1324  return 'if (RTEarea[' . GeneralUtility::quoteJSvalue($textareaId) . ']) { document.' . $formName . '[' . GeneralUtility::quoteJSvalue($textareaName) . '].value = RTEarea[' . GeneralUtility::quoteJSvalue($textareaId) . '].editor.getHTML(); } else { OK = 0; };';
1325  }
1326 
1337  public function setDeleteRTE($RTEcounter, $formName, $textareaId) {
1338  return 'if (RTEarea[' . GeneralUtility::quoteJSvalue($textareaId) . ']) { RTEarea[' . GeneralUtility::quoteJSvalue($textareaId) . '].deleted = true;}';
1339  }
1340 
1347  public function is_FE() {
1348  return is_object($GLOBALS['TSFE']) && !$this->isFrontendEditActive() && TYPO3_MODE == 'FE';
1349  }
1350 
1356  public function isFrontendEditActive() {
1357  return is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->beUserLogin && $GLOBALS['BE_USER']->frontendEdit instanceof \TYPO3\CMS\Core\FrontendEditing\FrontendEditingController;
1358  }
1359 
1367  public function clientInfo($userAgent = '') {
1368  if (!$userAgent) {
1369  $userAgent = GeneralUtility::getIndpEnv('HTTP_USER_AGENT');
1370  }
1371  $browserInfo = \TYPO3\CMS\Core\Utility\ClientUtility::getBrowserInfo($userAgent);
1372  // Known engines: order is not irrelevant!
1373  $knownEngines = array('opera', 'msie', 'edge', 'gecko', 'webkit');
1374  if (is_array($browserInfo['all'])) {
1375  foreach ($knownEngines as $engine) {
1376  if ($browserInfo['all'][$engine]) {
1377  $browserInfo['browser'] = $engine;
1378  $browserInfo['version'] = \TYPO3\CMS\Core\Utility\ClientUtility::getVersion($browserInfo['all'][$engine]);
1379  break;
1380  }
1381  }
1382  }
1383  return $browserInfo;
1384  }
1385 
1394  public function logDeprecatedProperty($deprecatedProperty, $useProperty, $version) {
1395  if (!$this->thisConfig['logDeprecatedProperties.']['disabled']) {
1396  $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);
1397  GeneralUtility::deprecationLog($message);
1398  if (is_object($GLOBALS['BE_USER']) && $this->thisConfig['logDeprecatedProperties.']['logAlsoToBELog']) {
1399  $message = sprintf($GLOBALS['LANG']->getLL('deprecatedPropertyMessage'), $deprecatedProperty, $useProperty, $version, $this->thePid);
1400  $GLOBALS['BE_USER']->simplelog($message, $this->ID);
1401  }
1402  }
1403  }
1404 
1405  /***************************
1406  *
1407  * OTHER FUNCTIONS: (from Classic RTE)
1408  *
1409  ***************************/
1415  public function RTEtsConfigParams() {
1416  if ($this->is_FE()) {
1417  return '';
1418  } else {
1419  $p = BackendUtility::getSpecConfParametersFromArray($this->specConf['rte_transform']['parameters']);
1420  return $this->elementParts[0] . ':' . $this->elementParts[1] . ':' . $this->elementParts[2] . ':' . $this->thePid . ':' . $this->typeVal . ':' . $this->tscPID . ':' . $p['imgpath'];
1421  }
1422  }
1423 
1424  public function cleanList($str) {
1425  if (strstr($str, '*')) {
1426  $str = '*';
1427  } else {
1428  $str = implode(',', array_unique(GeneralUtility::trimExplode(',', $str, TRUE)));
1429  }
1430  return $str;
1431  }
1432 
1436  public function filterStyleEl($elValue, $matchList) {
1437  $matchParts = GeneralUtility::trimExplode(',', $matchList, TRUE);
1438  $styleParts = explode(';', $elValue);
1439  $nStyle = array();
1440  foreach ($styleParts as $k => $p) {
1441  $pp = GeneralUtility::trimExplode(':', $p);
1442  if ($pp[0] && $pp[1]) {
1443  foreach ($matchParts as $el) {
1444  $star = substr($el, -1) == '*';
1445  if ($pp[0] === (string)$el || $star && GeneralUtility::isFirstPartOfStr($pp[0], substr($el, 0, -1))) {
1446  $nStyle[] = $pp[0] . ':' . $pp[1];
1447  } else {
1448  unset($styleParts[$k]);
1449  }
1450  }
1451  } else {
1452  unset($styleParts[$k]);
1453  }
1454  }
1455  return implode('; ', $nStyle);
1456  }
1457 
1458  // Hook on lorem_ipsum extension to insert text into the RTE in wysiwyg mode
1463  public function loremIpsumInsert($params) {
1464  GeneralUtility::logDeprecatedFunction();
1465  return '
1466  if (typeof(lorem_ipsum) == \'function\' && ' . $params['element'] . '.tagName.toLowerCase() == \'textarea\' ) lorem_ipsum(' . $params['element'] . ', lipsum_temp_strings[lipsum_temp_pointer]);
1467  ';
1468  }
1469 
1470 }
$TYPO3_CONF_VARS['SYS']['contentTable']
drawRTE(&$pObj, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue)
Definition: AbstractRte.php:77
setSaveRTE($RTEcounter, $formName, $textareaId, $textareaName)
$uid
Definition: server.php:36
static getUserObj($classRef, $checkPrefix='', $silent=FALSE)
static trimExplode($delim, $string, $removeEmptyValues=FALSE, $limit=0)
setDeleteRTE($RTEcounter, $formName, $textareaId)
addStyleSheet($key, $href, $title='', $relation='stylesheet')
static createVersionNumberedFilename($file, $forceQueryString=FALSE)
transformContent($dirRTE, $value, $table, $field, $row, $specConf, $thisConfig, $RTErelPath, $pid)
registerRTEinJS($RTEcounter, $table='', $uid='', $field='', $textAreaId='')
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]
static getFileAbsFileName($filename, $onlyRelative=TRUE, $relToTYPO3_mainDir=FALSE)
static getPagesTSconfig($id, $rootLine=NULL, $returnPartArray=FALSE)
$locales
Definition: be_users.php:6
static deleteClause($table, $tableAlias='')