TYPO3 CMS  TYPO3_7-6
RichTextElement.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
32 
37 {
43  protected $resultArray;
44 
51  protected $pidOfPageRecord;
52 
62 
81 
89 
95  protected $domIdentifier;
96 
102  protected $defaultExtras;
103 
109  protected $client;
110 
116  protected $language;
117 
124 
131 
138 
145 
152  'space' => 'space',
153  'bar' => 'separator',
154  'linebreak' => 'linebreak'
155  ];
156 
162  protected $toolbar = [];
163 
169  protected $toolbarOrderArray = [];
170 
176  protected $pluginButton = [];
177 
183  protected $pluginLabel = [];
184 
190  protected $pluginEnabledArray = [];
191 
198 
204  protected $registeredPlugins = [];
205 
212  public function render()
213  {
214  $table = $this->data['tableName'];
215  $fieldName = $this->data['fieldName'];
216  $row = $this->data['databaseRow'];
217  $parameterArray = $this->data['parameterArray'];
218 
219  $backendUser = $this->getBackendUserAuthentication();
220 
221  $this->resultArray = $this->initializeResultArray();
222  $this->defaultExtras = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
223  $this->pidOfPageRecord = $this->data['effectivePid'];
224  BackendUtility::fixVersioningPid($table, $row);
225  $this->pidOfVersionedMotherRecord = (int)$row['pid'];
226  $this->vanillaRteTsConfig = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($this->pidOfPageRecord));
227  $this->processedRteConfiguration = BackendUtility::RTEsetup(
228  $this->vanillaRteTsConfig['properties'],
229  $table,
230  $fieldName,
231  $this->data['recordTypeValue']
232  );
233  $this->client = $this->clientInfo();
234  $this->domIdentifier = preg_replace('/[^a-zA-Z0-9_:.-]/', '_', $parameterArray['itemFormElName']);
235  $this->domIdentifier = htmlspecialchars(preg_replace('/^[^a-zA-Z]/', 'x', $this->domIdentifier));
236 
237  $this->initializeLanguageRelatedProperties();
238 
239  // Get skin file name from Page TSConfig if any
240  $skinFilename = trim($this->processedRteConfiguration['skin']) ?: 'EXT:rtehtmlarea/Resources/Public/Css/Skin/htmlarea.css';
241  $skinFilename = $this->getFullFileName($skinFilename);
242  $skinDirectory = dirname($skinFilename);
243 
244  // jQuery UI Resizable style sheet and main skin stylesheet
245  $this->resultArray['stylesheetFiles'][] = $skinDirectory . '/jquery-ui-resizable.css';
246  $this->resultArray['stylesheetFiles'][] = $skinFilename;
247 
248  $this->enableRegisteredPlugins();
249 
250  // Configure toolbar
251  $this->setToolbar();
252 
253  // Check if some plugins need to be disabled
254  $this->setPlugins();
255 
256  // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
257  $this->pluginEnabledCumulativeArray = $this->pluginEnabledArray;
258 
259  $this->addInstanceJavaScriptRegistration();
260 
261  $this->addOnSubmitJavaScriptCode();
262 
263  // Add RTE JavaScript
264  $this->loadRequireModulesForRTE();
265 
266  // Create language labels
267  $this->createJavaScriptLanguageLabelsFromFiles();
268 
269  // Get RTE init JS code
270  $this->resultArray['additionalJavaScriptPost'][] = $this->getRteInitJsCode();
271 
272  $html = $this->getMainHtml();
273 
274  $this->resultArray['html'] = $this->renderWizards(
275  [$html],
276  $parameterArray['fieldConf']['config']['wizards'],
277  $table,
278  $row,
279  $fieldName,
280  $parameterArray,
281  $parameterArray['itemFormElName'],
282  $this->defaultExtras,
283  true
284  );
285 
286  return $this->resultArray;
287  }
288 
294  protected function getMainHtml()
295  {
296  $backendUser = $this->getBackendUserAuthentication();
297 
298  if ($this->isInFullScreenMode()) {
299  $width = '100%';
300  $height = '100%';
301  $paddingRight = '0px';
302  $editorWrapWidth = '100%';
303  } else {
304  $options = $backendUser->userTS['options.'];
305  $width = 530 + (isset($options['RTELargeWidthIncrement']) ? (int)$options['RTELargeWidthIncrement'] : 150);
307  $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
308  $inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
309  $inlineStructureDepth = $inlineStackProcessor->getStructureDepth();
310  $width -= $inlineStructureDepth > 0 ? ($inlineStructureDepth + 1) * 12 : 0;
311  $widthOverride = isset($backendUser->uc['rteWidth']) && trim($backendUser->uc['rteWidth']) ? trim($backendUser->uc['rteWidth']) : trim($this->processedRteConfiguration['RTEWidthOverride']);
312  if ($widthOverride) {
313  if (strstr($widthOverride, '%')) {
314  if ($this->client['browser'] !== 'msie') {
315  $width = (int)$widthOverride > 0 ? (int)$widthOverride : '100%';
316  }
317  } else {
318  $width = (int)$widthOverride > 0 ? (int)$widthOverride : $width;
319  }
320  }
321  $width = strstr($width, '%') ? $width : $width . 'px';
322  $height = 380 + (isset($options['RTELargeHeightIncrement']) ? (int)$options['RTELargeHeightIncrement'] : 0);
323  $heightOverride = isset($backendUser->uc['rteHeight']) && (int)$backendUser->uc['rteHeight'] ? (int)$backendUser->uc['rteHeight'] : (int)$this->processedRteConfiguration['RTEHeightOverride'];
324  $height = $heightOverride > 0 ? $heightOverride . 'px' : $height . 'px';
325  $paddingRight = '2';
326  $editorWrapWidth = '99%';
327  }
328  $rteDivStyle = 'position:relative; left:0px; top:0px; height:' . $height . '; width:' . $width . '; border: 1px solid black; padding: 2 ' . $paddingRight . ' 2 2;';
329 
330  $itemFormElementName = $this->data['parameterArray']['itemFormElName'];
331 
332  // This seems to result in:
333  // _TRANSFORM_bodytext (the handled field name) in case the field is a direct DB field
334  // _TRANSFORM_vDEF (constant string) in case the RTE is within a flex form
335  $triggerFieldName = preg_replace('/\\[([^]]+)\\]$/', '[_TRANSFORM_\\1]', $itemFormElementName);
336 
337  $value = $this->transformDatabaseContentToEditor($this->data['parameterArray']['itemFormElValue']);
338 
339  $result = [];
340  // The hidden field tells the DataHandler that processing should be done on this value.
341  $result[] = '<input type="hidden" name="' . htmlspecialchars($triggerFieldName) . '" value="RTE" />';
342  $result[] = '<div id="pleasewait' . $this->domIdentifier . '" class="pleasewait" style="display: block;" >';
343  $result[] = $this->getLanguageService()->sL('LLL:EXT:rtehtmlarea/Resources/Private/Language/locallang.xlf:Please wait');
344  $result[] = '</div>';
345  $result[] = '<div id="editorWrap' . $this->domIdentifier . '" class="editorWrap" style="visibility: hidden; width:' . $editorWrapWidth . '; height:100%;">';
346  $result[] = '<textarea ' . $this->getValidationDataAsDataAttribute($this->data['parameterArray']['fieldConf']['config']) . ' id="RTEarea' . $this->domIdentifier . '" name="' . htmlspecialchars($itemFormElementName) . '" rows="0" cols="0" style="' . htmlspecialchars($rteDivStyle) . '">';
347  $result[] = htmlspecialchars($value);
348  $result[] = '</textarea>';
349  $result[] = '</div>';
350 
351  return implode(LF, $result);
352  }
353 
359  protected function enableRegisteredPlugins()
360  {
361  // Traverse registered plugins
362  if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins'])) {
363  foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['plugins'] as $pluginId => $pluginObjectConfiguration) {
364  if (is_array($pluginObjectConfiguration) && isset($pluginObjectConfiguration['objectReference'])) {
366  $plugin = GeneralUtility::makeInstance($pluginObjectConfiguration['objectReference']);
367  $configuration = [
368  'language' => $this->language,
369  'contentTypo3Language' => $this->contentTypo3Language,
370  'contentISOLanguage' => $this->contentISOLanguage,
371  'contentLanguageUid' => $this->contentLanguageUid,
372  'RTEsetup' => $this->vanillaRteTsConfig,
373  'client' => $this->client,
374  'thisConfig' => $this->processedRteConfiguration,
375  'specConf' => $this->defaultExtras,
376  ];
377  if ($plugin->main($configuration)) {
378  $this->registeredPlugins[$pluginId] = $plugin;
379  // Override buttons from previously registered plugins
380  $pluginButtons = GeneralUtility::trimExplode(',', $plugin->getPluginButtons(), true);
381  foreach ($this->pluginButton as $previousPluginId => $buttonList) {
382  $this->pluginButton[$previousPluginId] = implode(',', array_diff(GeneralUtility::trimExplode(',', $this->pluginButton[$previousPluginId], true), $pluginButtons));
383  }
384  $this->pluginButton[$pluginId] = $plugin->getPluginButtons();
385  $pluginLabels = GeneralUtility::trimExplode(',', $plugin->getPluginLabels(), true);
386  foreach ($this->pluginLabel as $previousPluginId => $labelList) {
387  $this->pluginLabel[$previousPluginId] = implode(',', array_diff(GeneralUtility::trimExplode(',', $this->pluginLabel[$previousPluginId], true), $pluginLabels));
388  }
389  $this->pluginLabel[$pluginId] = $plugin->getPluginLabels();
390  $this->pluginEnabledArray[] = $pluginId;
391  }
392  }
393  }
394  }
395  // Process overrides
396  $hidePlugins = [];
397  foreach ($this->registeredPlugins as $pluginId => $plugin) {
399  if ($plugin->addsButtons() && !$this->pluginButton[$pluginId]) {
400  $hidePlugins[] = $pluginId;
401  }
402  }
403  $this->pluginEnabledArray = array_unique(array_diff($this->pluginEnabledArray, $hidePlugins));
404  }
405 
411  protected function setToolbar()
412  {
413  $backendUser = $this->getBackendUserAuthentication();
414 
415  if ($this->client['browser'] === 'msie' || $this->client['browser'] === 'opera') {
416  $this->processedRteConfiguration['keepButtonGroupTogether'] = 0;
417  }
418  $this->defaultToolbarOrder = 'bar, blockstylelabel, blockstyle, textstylelabel, textstyle, linebreak,
419  bar, formattext, bold, strong, italic, emphasis, big, small, insertedtext, deletedtext, citation, code,'
420  . 'definition, keyboard, monospaced, quotation, sample, variable, bidioverride, strikethrough, subscript, superscript, underline, span,
421  bar, fontstyle, fontsize, bar, formatblock, insertparagraphbefore, insertparagraphafter, blockquote, line,
422  bar, left, center, right, justifyfull,
423  bar, orderedlist, unorderedlist, definitionlist, definitionitem, outdent, indent,
424  bar, language, showlanguagemarks,lefttoright, righttoleft,
425  bar, textcolor, bgcolor, textindicator,
426  bar, editelement, showmicrodata,
427  bar, image, emoticon, insertcharacter, insertsofthyphen, abbreviation, user,
428  bar, link, unlink,
429  bar, table,'
430  . ($this->processedRteConfiguration['hideTableOperationsInToolbar']
431  && is_array($this->processedRteConfiguration['buttons.'])
432  && is_array($this->processedRteConfiguration['buttons.']['toggleborders.'])
433  && $this->processedRteConfiguration['buttons.']['toggleborders.']['keepInToolbar'] ? ' toggleborders,' : '')
434  . 'bar, findreplace, spellcheck,
435  bar, chMode, inserttag, removeformat, bar, copy, cut, paste, pastetoggle, pastebehaviour, bar, undo, redo, bar, about, linebreak,'
436  . ($this->processedRteConfiguration['hideTableOperationsInToolbar'] ? '' : 'bar, toggleborders,')
437  . ' bar, tableproperties, tablerestyle, bar, rowproperties, rowinsertabove, rowinsertunder, rowdelete, rowsplit, bar,
438  columnproperties, columninsertbefore, columninsertafter, columndelete, columnsplit, bar,
439  cellproperties, cellinsertbefore, cellinsertafter, celldelete, cellsplit, cellmerge';
440 
441  // Additional buttons from registered plugins
442  foreach ($this->registeredPlugins as $pluginId => $plugin) {
444  if ($this->isPluginEnabled($pluginId)) {
445  $pluginButtons = $plugin->getPluginButtons();
446  //Add only buttons not yet in the default toolbar order
447  $addButtons = implode(
448  ',',
449  array_diff(
450  GeneralUtility::trimExplode(',', $pluginButtons, true),
451  GeneralUtility::trimExplode(',', $this->defaultToolbarOrder, true)
452  )
453  );
454  $this->defaultToolbarOrder = ($addButtons ? 'bar,' . $addButtons . ',linebreak,' : '') . $this->defaultToolbarOrder;
455  }
456  }
457  $toolbarOrder = $this->processedRteConfiguration['toolbarOrder'] ?: $this->defaultToolbarOrder;
458  // Getting rid of undefined buttons
459  $this->toolbarOrderArray = array_intersect(GeneralUtility::trimExplode(',', $toolbarOrder, true), GeneralUtility::trimExplode(',', $this->defaultToolbarOrder, true));
460  $toolbarOrder = array_unique(array_values($this->toolbarOrderArray));
461  // Fetching specConf for field from backend
462  $pList = is_array($this->defaultExtras['richtext']['parameters']) ? implode(',', $this->defaultExtras['richtext']['parameters']) : '';
463  if ($pList !== '*') {
464  // If not all
465  $show = is_array($this->defaultExtras['richtext']['parameters']) ? $this->defaultExtras['richtext']['parameters'] : [];
466  if ($this->processedRteConfiguration['showButtons']) {
467  if (!GeneralUtility::inList($this->processedRteConfiguration['showButtons'], '*')) {
468  $show = array_unique(array_merge($show, GeneralUtility::trimExplode(',', $this->processedRteConfiguration['showButtons'], true)));
469  } else {
470  $show = array_unique(array_merge($show, $toolbarOrder));
471  }
472  }
473  if (is_array($this->processedRteConfiguration['showButtons.'])) {
474  foreach ($this->processedRteConfiguration['showButtons.'] as $buttonId => $value) {
475  if ($value) {
476  $show[] = $buttonId;
477  }
478  }
479  $show = array_unique($show);
480  }
481  } else {
482  $show = $toolbarOrder;
483  }
484  $RTEkeyList = isset($backendUser->userTS['options.']['RTEkeyList']) ? $backendUser->userTS['options.']['RTEkeyList'] : '*';
485  if ($RTEkeyList !== '*') {
486  // If not all
487  $show = array_intersect($show, GeneralUtility::trimExplode(',', $RTEkeyList, true));
488  }
489  // Hiding buttons of disabled plugins
490  $hideButtons = ['space', 'bar', 'linebreak'];
491  foreach ($this->pluginButton as $pluginId => $buttonList) {
492  if (!$this->isPluginEnabled($pluginId)) {
493  $buttonArray = GeneralUtility::trimExplode(',', $buttonList, true);
494  foreach ($buttonArray as $button) {
495  $hideButtons[] = $button;
496  }
497  }
498  }
499  // Hiding labels of disabled plugins
500  foreach ($this->pluginLabel as $pluginId => $label) {
501  if (!$this->isPluginEnabled($pluginId)) {
502  $hideButtons[] = $label;
503  }
504  }
505  // Hiding buttons
506  $show = array_diff($show, GeneralUtility::trimExplode(',', $this->processedRteConfiguration['hideButtons'], true));
507  // Apply toolbar constraints from registered plugins
508  foreach ($this->registeredPlugins as $pluginId => $plugin) {
509  if ($this->isPluginEnabled($pluginId) && method_exists($plugin, 'applyToolbarConstraints')) {
510  $show = $plugin->applyToolbarConstraints($show);
511  }
512  }
513  // Getting rid of the buttons for which we have no position
514  $show = array_intersect($show, $toolbarOrder);
515  foreach ($this->registeredPlugins as $pluginId => $plugin) {
517  $plugin->setToolbar($show);
518  }
519  $this->toolbar = $show;
520  }
521 
527  protected function setPlugins()
528  {
529  // Disabling a plugin that adds buttons if none of its buttons is in the toolbar
530  $hidePlugins = [];
531  foreach ($this->pluginButton as $pluginId => $buttonList) {
533  $plugin = $this->registeredPlugins[$pluginId];
534  if ($plugin->addsButtons()) {
535  $showPlugin = false;
536  $buttonArray = GeneralUtility::trimExplode(',', $buttonList, true);
537  foreach ($buttonArray as $button) {
538  if (in_array($button, $this->toolbar)) {
539  $showPlugin = true;
540  }
541  }
542  if (!$showPlugin) {
543  $hidePlugins[] = $pluginId;
544  }
545  }
546  }
547  $this->pluginEnabledArray = array_diff($this->pluginEnabledArray, $hidePlugins);
548  // Hiding labels of disabled plugins
549  $hideLabels = [];
550  foreach ($this->pluginLabel as $pluginId => $label) {
551  if (!$this->isPluginEnabled($pluginId)) {
552  $hideLabels[] = $label;
553  }
554  }
555  $this->toolbar = array_diff($this->toolbar, $hideLabels);
556  // Adding plugins declared as prerequisites by enabled plugins
557  $requiredPlugins = [];
558  foreach ($this->registeredPlugins as $pluginId => $plugin) {
560  if ($this->isPluginEnabled($pluginId)) {
561  $requiredPlugins = array_merge($requiredPlugins, GeneralUtility::trimExplode(',', $plugin->getRequiredPlugins(), true));
562  }
563  }
564  $requiredPlugins = array_unique($requiredPlugins);
565  foreach ($requiredPlugins as $pluginId) {
566  if (is_object($this->registeredPlugins[$pluginId]) && !$this->isPluginEnabled($pluginId)) {
567  $this->pluginEnabledArray[] = $pluginId;
568  }
569  }
570  $this->pluginEnabledArray = array_unique($this->pluginEnabledArray);
571  // Completing the toolbar conversion array for htmlArea
572  foreach ($this->registeredPlugins as $pluginId => $plugin) {
574  if ($this->isPluginEnabled($pluginId)) {
575  $this->convertToolbarForHtmlAreaArray = array_unique(array_merge($this->convertToolbarForHtmlAreaArray, $plugin->getConvertToolbarForHtmlAreaArray()));
576  }
577  }
578  }
579 
585  protected function loadRequireModulesForRTE()
586  {
587  $this->resultArray['requireJsModules'] = [];
588  $this->resultArray['requireJsModules'][] = 'TYPO3/CMS/Rtehtmlarea/HTMLArea/HTMLArea';
589  foreach ($this->pluginEnabledCumulativeArray as $pluginId) {
591  $plugin = $this->registeredPlugins[$pluginId];
592  $extensionKey = is_object($plugin) ? $plugin->getExtensionKey() : 'rtehtmlarea';
593  $requirePath = 'TYPO3/CMS/' . GeneralUtility::underscoredToUpperCamelCase($extensionKey);
594  $this->resultArray['requireJsModules'][] = $requirePath . '/Plugins/' . $pluginId;
595  }
596  }
597 
603  protected function getRteInitJsCode()
604  {
605  $skinFilename = trim($this->processedRteConfiguration['skin']) ?: 'EXT:rtehtmlarea/Resources/Public/Css/Skin/htmlarea.css';
606  $skinFilename = $this->getFullFileName($skinFilename);
607  $skinDirectory = dirname($skinFilename);
608  // Editing area style sheet
609  $editedContentCSS = GeneralUtility::createVersionNumberedFilename($skinDirectory . '/htmlarea-edited-content.css');
610 
611  return 'require(["TYPO3/CMS/Rtehtmlarea/HTMLArea/HTMLArea"], function (HTMLArea) {
612  if (typeof RTEarea === "undefined") {
613  RTEarea = new Object();
614  RTEarea[0] = new Object();
615  RTEarea[0].version = "' . $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['rtehtmlarea']['version'] . '";
616  RTEarea[0].editorUrl = "' . ExtensionManagementUtility::extRelPath('rtehtmlarea') . '";
617  RTEarea[0].editorSkin = "' . $skinDirectory . '/";
618  RTEarea[0].editedContentCSS = "' . $editedContentCSS . '";
619  RTEarea.init = function() {
620  if (typeof HTMLArea === "undefined" || !Ext.isReady) {
621  window.setTimeout(function () {
622  RTEarea.init();
623  }, 10);
624  } else {
625  HTMLArea.init();
626  }
627  };
628  RTEarea.initEditor = function(editorNumber) {
629  if (typeof HTMLArea === "undefined" || !HTMLArea.isReady) {
630  window.setTimeout(function () {
631  RTEarea.initEditor(editorNumber);
632  }, 40);
633  } else {
634  HTMLArea.initEditor(editorNumber);
635  }
636  };
637  }
638  RTEarea.init();
639  });';
640  }
641 
647  protected function addInstanceJavaScriptRegistration()
648  {
649  $backendUser = $this->getBackendUserAuthentication();
650 
651  $jsArray = [];
652  $jsArray[] = 'if (typeof configureEditorInstance === "undefined") {';
653  $jsArray[] = ' configureEditorInstance = new Object();';
654  $jsArray[] = '}';
655  $jsArray[] = 'configureEditorInstance[' . GeneralUtility::quoteJSvalue($this->domIdentifier) . '] = function() {';
656  $jsArray[] = 'if (typeof RTEarea === "undefined" || typeof HTMLArea === "undefined") {';
657  $jsArray[] = ' window.setTimeout("configureEditorInstance[' . GeneralUtility::quoteJSvalue($this->domIdentifier) . ']();", 40);';
658  $jsArray[] = '} else {';
659  $jsArray[] = 'editornumber = ' . GeneralUtility::quoteJSvalue($this->domIdentifier) . ';';
660  $jsArray[] = 'RTEarea[editornumber] = new Object();';
661  $jsArray[] = 'RTEarea[editornumber].RTEtsConfigParams = "&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams()) . '";';
662  $jsArray[] = 'RTEarea[editornumber].uidOfPageRecord = "&id=' . (int)$this->pidOfPageRecord . '";';
663  $jsArray[] = 'RTEarea[editornumber].number = editornumber;';
664  $jsArray[] = 'RTEarea[editornumber].deleted = false;';
665  $jsArray[] = 'RTEarea[editornumber].textAreaId = ' . GeneralUtility::quoteJSvalue($this->domIdentifier) . ';';
666  $jsArray[] = 'RTEarea[editornumber].id = "RTEarea" + editornumber;';
667  $jsArray[] = 'RTEarea[editornumber].RTEWidthOverride = "'
668  . (isset($backendUser->uc['rteWidth']) && trim($backendUser->uc['rteWidth'])
669  ? trim($backendUser->uc['rteWidth'])
670  : trim($this->processedRteConfiguration['RTEWidthOverride'])) . '";';
671  $jsArray[] = 'RTEarea[editornumber].RTEHeightOverride = "'
672  . (isset($backendUser->uc['rteHeight']) && (int)$backendUser->uc['rteHeight']
673  ? (int)$backendUser->uc['rteHeight']
674  : (int)$this->processedRteConfiguration['RTEHeightOverride']) . '";';
675  $jsArray[] = 'RTEarea[editornumber].resizable = '
676  . (isset($backendUser->uc['rteResize']) && $backendUser->uc['rteResize']
677  ? 'true;'
678  : (trim($this->processedRteConfiguration['rteResize']) ? 'true;' : 'false;'));
679  $jsArray[] = 'RTEarea[editornumber].maxHeight = "'
680  . (isset($backendUser->uc['rteMaxHeight']) && (int)$backendUser->uc['rteMaxHeight']
681  ? trim($backendUser->uc['rteMaxHeight'])
682  : ((int)$this->processedRteConfiguration['rteMaxHeight'] ?: '2000')) . '";';
683  $jsArray[] = 'RTEarea[editornumber].fullScreen = ' . ($this->isInFullScreenMode() ? 'true;' : 'false;');
684  $jsArray[] = 'RTEarea[editornumber].showStatusBar = ' . (trim($this->processedRteConfiguration['showStatusBar']) ? 'true;' : 'false;');
685  $jsArray[] = 'RTEarea[editornumber].enableWordClean = ' . (trim($this->processedRteConfiguration['enableWordClean']) ? 'true;' : 'false;');
686  $jsArray[] = 'RTEarea[editornumber].htmlRemoveComments = ' . (trim($this->processedRteConfiguration['removeComments']) ? 'true;' : 'false;');
687  $jsArray[] = 'RTEarea[editornumber].disableEnterParagraphs = ' . (trim($this->processedRteConfiguration['disableEnterParagraphs']) ? 'true;' : 'false;');
688  $jsArray[] = 'RTEarea[editornumber].disableObjectResizing = ' . (trim($this->processedRteConfiguration['disableObjectResizing']) ? 'true;' : 'false;');
689  $jsArray[] = 'RTEarea[editornumber].removeTrailingBR = ' . (trim($this->processedRteConfiguration['removeTrailingBR']) ? 'true;' : 'false;');
690  $jsArray[] = 'RTEarea[editornumber].useCSS = ' . (trim($this->processedRteConfiguration['useCSS']) ? 'true' : 'false') . ';';
691  $jsArray[] = 'RTEarea[editornumber].keepButtonGroupTogether = ' . (trim($this->processedRteConfiguration['keepButtonGroupTogether']) ? 'true;' : 'false;');
692  $jsArray[] = 'RTEarea[editornumber].disablePCexamples = ' . (trim($this->processedRteConfiguration['disablePCexamples']) ? 'true;' : 'false;');
693  $jsArray[] = 'RTEarea[editornumber].showTagFreeClasses = ' . (trim($this->processedRteConfiguration['showTagFreeClasses']) ? 'true;' : 'false;');
694  $jsArray[] = 'RTEarea[editornumber].tceformsNested = ' . (!empty($this->data) ? json_encode($this->data['tabAndInlineStack']) : '[]') . ';';
695  $jsArray[] = 'RTEarea[editornumber].dialogueWindows = new Object();';
696  if (isset($this->processedRteConfiguration['dialogueWindows.']['defaultPositionFromTop'])) {
697  $jsArray[] = 'RTEarea[editornumber].dialogueWindows.positionFromTop = ' . (int)$this->processedRteConfiguration['dialogueWindows.']['defaultPositionFromTop'] . ';';
698  }
699  if (isset($this->processedRteConfiguration['dialogueWindows.']['defaultPositionFromLeft'])) {
700  $jsArray[] = 'RTEarea[editornumber].dialogueWindows.positionFromLeft = ' . (int)$this->processedRteConfiguration['dialogueWindows.']['defaultPositionFromLeft'] . ';';
701  }
702  $jsArray[] = 'RTEarea[editornumber].sys_language_content = "' . $this->contentLanguageUid . '";';
703  $jsArray[] = 'RTEarea[editornumber].typo3ContentLanguage = "' . $this->contentTypo3Language . '";';
704  $jsArray[] = 'RTEarea[editornumber].userUid = "' . 'BE_' . $backendUser->user['uid'] . '";';
705 
706  // Setting the plugin flags
707  $jsArray[] = 'RTEarea[editornumber].plugin = new Object();';
708  foreach ($this->pluginEnabledArray as $pluginId) {
709  $jsArray[] = 'RTEarea[editornumber].plugin.' . $pluginId . ' = true;';
710  }
711 
712  // Setting the buttons configuration
713  $jsArray[] = 'RTEarea[editornumber].buttons = new Object();';
714  if (is_array($this->processedRteConfiguration['buttons.'])) {
715  foreach ($this->processedRteConfiguration['buttons.'] as $buttonIndex => $conf) {
716  $button = substr($buttonIndex, 0, -1);
717  if (is_array($conf)) {
718  $jsArray[] = 'RTEarea[editornumber].buttons.' . $button . ' = ' . $this->buildNestedJSArray($conf) . ';';
719  }
720  }
721  }
722 
723  // Setting the list of tags to be removed if specified in the RTE config
724  if (trim($this->processedRteConfiguration['removeTags'])) {
725  $jsArray[] = 'RTEarea[editornumber].htmlRemoveTags = /^(' . implode('|', GeneralUtility::trimExplode(',', $this->processedRteConfiguration['removeTags'], true)) . ')$/i;';
726  }
727 
728  // Setting the list of tags to be removed with their contents if specified in the RTE config
729  if (trim($this->processedRteConfiguration['removeTagsAndContents'])) {
730  $jsArray[] = 'RTEarea[editornumber].htmlRemoveTagsAndContents = /^(' . implode('|', GeneralUtility::trimExplode(',', $this->processedRteConfiguration['removeTagsAndContents'], true)) . ')$/i;';
731  }
732 
733  // Setting array of custom tags if specified in the RTE config
734  if (!empty($this->processedRteConfiguration['customTags'])) {
735  $customTags = GeneralUtility::trimExplode(',', $this->processedRteConfiguration['customTags'], true);
736  if (!empty($customTags)) {
737  $jsArray[] = 'RTEarea[editornumber].customTags= ' . json_encode($customTags) . ';';
738  }
739  }
740 
741  // Setting array of content css files if specified in the RTE config
742  $versionNumberedFileNames = [];
743  $contentCssFileNames = $this->getContentCssFileNames();
744  foreach ($contentCssFileNames as $contentCssFileName) {
745  $versionNumberedFileNames[] = GeneralUtility::createVersionNumberedFilename($contentCssFileName);
746  }
747  $jsArray[] = 'RTEarea[editornumber].pageStyle = ["' . implode('","', $versionNumberedFileNames) . '"];';
748 
749  $jsArray[] = 'RTEarea[editornumber].classesUrl = "' . $this->writeTemporaryFile(('classes_' . $this->language), 'js', $this->buildJSClassesArray()) . '";';
750 
751  // Add Javascript configuration for registered plugins
752  foreach ($this->registeredPlugins as $pluginId => $plugin) {
754  if ($this->isPluginEnabled($pluginId)) {
755  $jsPluginString = $plugin->buildJavascriptConfiguration();
756  if ($jsPluginString) {
757  $jsArray[] = $plugin->buildJavascriptConfiguration();
758  }
759  }
760  }
761 
762  // Avoid premature reference to HTMLArea when being initially loaded by IRRE Ajax call
763  $jsArray[] = 'RTEarea[editornumber].toolbar = ' . $this->getJSToolbarArray() . ';';
764  $jsArray[] = 'RTEarea[editornumber].convertButtonId = ' . json_encode(array_flip($this->convertToolbarForHtmlAreaArray)) . ';';
765  $jsArray[] = 'RTEarea.initEditor(editornumber);';
766  $jsArray[] = '}';
767  $jsArray[] = '}';
768  $jsArray[] = 'configureEditorInstance[' . GeneralUtility::quoteJSvalue($this->domIdentifier) . ']();';
769 
770  $this->resultArray['additionalJavaScriptPost'][] = implode(LF, $jsArray);
771  }
772 
778  protected function getContentCssFileNames()
779  {
780  $contentCss = is_array($this->processedRteConfiguration['contentCSS.']) ? $this->processedRteConfiguration['contentCSS.'] : [];
781  if (isset($this->processedRteConfiguration['contentCSS'])) {
782  $contentCss[] = trim($this->processedRteConfiguration['contentCSS']);
783  }
784  $contentCssFiles = [];
785  if (!empty($contentCss)) {
786  foreach ($contentCss as $contentCssKey => $contentCssfile) {
787  $fileName = trim($contentCssfile);
788  $absolutePath = GeneralUtility::getFileAbsFileName($fileName);
789  if (file_exists($absolutePath) && filesize($absolutePath)) {
790  $contentCssFiles[$contentCssKey] = $this->getFullFileName($fileName);
791  }
792  }
793  } else {
794  // Fallback to default content css file if none of the configured files exists and is not empty
795  $contentCssFiles['default'] = $this->getFullFileName('EXT:rtehtmlarea/Resources/Public/Css/ContentCss/Default.css');
796  }
797  return array_unique($contentCssFiles);
798  }
799 
806  protected function isPluginEnabled($pluginId)
807  {
808  return in_array($pluginId, $this->pluginEnabledArray);
809  }
810 
816  protected function buildJSClassesArray()
817  {
818  $RTEProperties = $this->vanillaRteTsConfig['properties'];
819  // Declare sub-arrays
820  $classesArray = [
821  'labels' => [],
822  'values' => [],
823  'noShow' => [],
824  'alternating' => [],
825  'counting' => [],
826  'selectable' => [],
827  'requires' => [],
828  'requiredBy' => [],
829  'XOR' => []
830  ];
831  $JSClassesArray = '';
832  // Scanning the list of classes if specified in the RTE config
833  if (is_array($RTEProperties['classes.'])) {
834  foreach ($RTEProperties['classes.'] as $className => $conf) {
835  $className = rtrim($className, '.');
836 
837  $label = '';
838  if (!empty($conf['name'])) {
839  $label = $this->getLanguageService()->sL(trim($conf['name']));
840  $label = str_replace('"', '\\"', str_replace('\\\'', '\'', $label));
841  }
842  $classesArray['labels'][$className] = $label;
843  $classesArray['values'][$className] = str_replace('\\\'', '\'', $conf['value']);
844  if (isset($conf['noShow'])) {
845  $classesArray['noShow'][$className] = $conf['noShow'];
846  }
847  if (is_array($conf['alternating.'])) {
848  $classesArray['alternating'][$className] = $conf['alternating.'];
849  }
850  if (is_array($conf['counting.'])) {
851  $classesArray['counting'][$className] = $conf['counting.'];
852  }
853  if (isset($conf['selectable'])) {
854  $classesArray['selectable'][$className] = $conf['selectable'];
855  }
856  if (isset($conf['requires'])) {
857  $classesArray['requires'][$className] = explode(',', GeneralUtility::rmFromList($className, $this->cleanList($conf['requires'])));
858  }
859  }
860  // Remove circularities from classes dependencies
861  $requiringClasses = array_keys($classesArray['requires']);
862  foreach ($requiringClasses as $requiringClass) {
863  if ($this->hasCircularDependency($classesArray, $requiringClass, $requiringClass)) {
864  unset($classesArray['requires'][$requiringClass]);
865  }
866  }
867  // Reverse relationship for the dependency checks when removing styles
868  $requiringClasses = array_keys($classesArray['requires']);
869  foreach ($requiringClasses as $className) {
870  foreach ($classesArray['requires'][$className] as $requiredClass) {
871  if (!is_array($classesArray['requiredBy'][$requiredClass])) {
872  $classesArray['requiredBy'][$requiredClass] = [];
873  }
874  if (!in_array($className, $classesArray['requiredBy'][$requiredClass])) {
875  $classesArray['requiredBy'][$requiredClass][] = $className;
876  }
877  }
878  }
879  }
880  // Scanning the list of sets of mutually exclusives classes if specified in the RTE config
881  if (is_array($RTEProperties['mutuallyExclusiveClasses.'])) {
882  foreach ($RTEProperties['mutuallyExclusiveClasses.'] as $listName => $conf) {
883  $classSet = GeneralUtility::trimExplode(',', $conf, true);
884  $classList = implode(',', $classSet);
885  foreach ($classSet as $className) {
886  $classesArray['XOR'][$className] = '/^(' . implode('|', GeneralUtility::trimExplode(',', GeneralUtility::rmFromList($className, $classList), true)) . ')$/';
887  }
888  }
889  }
890  foreach ($classesArray as $key => $subArray) {
891  $JSClassesArray .= 'HTMLArea.classes' . ucfirst($key) . ' = ' . $this->buildNestedJSArray($subArray) . ';' . LF;
892  }
893  return $JSClassesArray;
894  }
895 
905  protected function hasCircularDependency(&$classesArray, $requiringClass, $initialClass, $recursionLevel = 0)
906  {
907  if (is_array($classesArray['requires'][$requiringClass])) {
908  if (in_array($initialClass, $classesArray['requires'][$requiringClass])) {
909  return true;
910  } else {
911  if ($recursionLevel++ < 20) {
912  foreach ($classesArray['requires'][$requiringClass] as $requiringClass2) {
913  if ($this->hasCircularDependency($classesArray, $requiringClass2, $initialClass, $recursionLevel)) {
914  return true;
915  }
916  }
917  }
918  return false;
919  }
920  } else {
921  return false;
922  }
923  }
924 
934  protected function buildNestedJSArray($conf)
935  {
936  $convertedConf = GeneralUtility::removeDotsFromTS($conf);
937  return str_replace(
938  [':"0"', ':"\\/^(', ')$\\/i"', ':"\\/^(', ')$\\/"', '[]'],
939  [':false', ':/^(', ')$/i', ':/^(', ')$/', '{}'], json_encode($convertedConf)
940  );
941  }
942 
952  protected function writeTemporaryFile($label, $fileExtension = 'js', $contents = '')
953  {
954  $relativeFilename = 'typo3temp/RteHtmlArea/' . str_replace('-', '_', $label) . '_' . GeneralUtility::shortMD5($contents, 20) . '.' . $fileExtension;
955  $destination = PATH_site . $relativeFilename;
956  if (!file_exists($destination)) {
957  $minifiedJavaScript = '';
958  if ($fileExtension === 'js' && $contents !== '') {
959  $minifiedJavaScript = GeneralUtility::minifyJavaScript($contents);
960  }
961  $failure = GeneralUtility::writeFileToTypo3tempDir($destination, $minifiedJavaScript ? $minifiedJavaScript : $contents);
962  if ($failure) {
963  throw new \RuntimeException($failure, 1294585668);
964  }
965  }
966  if (isset($GLOBALS['TSFE'])) {
967  $fileName = $relativeFilename;
968  } else {
969  $fileName = '../' . $relativeFilename;
970  }
971  return GeneralUtility::resolveBackPath($fileName);
972  }
973 
981  protected function createJavaScriptLanguageLabelsFromFiles()
982  {
983  $labelArray = [];
984  // Load labels of 3 base files into JS
985  foreach (['tooltips', 'msg', 'dialogs'] as $identifier) {
986  $fileName = 'EXT:rtehtmlarea/Resources/Private/Language/locallang_' . $identifier . '.xlf';
987  $newLabels = $this->getMergedLabelsFromFile($fileName);
988  if (!empty($newLabels)) {
989  $labelArray[$identifier] = $newLabels;
990  }
991  }
992  // Load labels of plugins into JS
993  foreach ($this->pluginEnabledCumulativeArray as $pluginId) {
995  $plugin = $this->registeredPlugins[$pluginId];
996  $extensionKey = is_object($plugin) ? $plugin->getExtensionKey() : 'rtehtmlarea';
997  $fileName = 'EXT:' . $extensionKey . '/Resources/Private/Language/Plugins/' . $pluginId . '/locallang_js.xlf';
998  $newLabels = $this->getMergedLabelsFromFile($fileName);
999  if (!empty($newLabels)) {
1000  $labelArray[$pluginId] = $newLabels;
1001  }
1002  }
1003  $javaScriptString = 'TYPO3.jQuery(function() {';
1004  $javaScriptString .= 'HTMLArea.I18N = new Object();' . LF;
1005  $javaScriptString .= 'HTMLArea.I18N = ' . json_encode($labelArray);
1006  $javaScriptString .= '});';
1007  $this->resultArray['additionalJavaScriptPost'][] = $javaScriptString;
1008  }
1009 
1017  protected function getMergedLabelsFromFile($fileName)
1018  {
1020  $languageFactory = GeneralUtility::makeInstance(LocalizationFactory::class);
1021  $localizationArray = $languageFactory->getParsedData($fileName, $this->language, 'utf-8', 1);
1022  if (is_array($localizationArray) && !empty($localizationArray)) {
1023  if (!empty($localizationArray[$this->language])) {
1024  $finalLocalLang = $localizationArray['default'];
1025  ArrayUtility::mergeRecursiveWithOverrule($finalLocalLang, $localizationArray[$this->language], true, false);
1026  $localizationArray[$this->language] = $finalLocalLang;
1027  } else {
1028  $localizationArray[$this->language] = $localizationArray['default'];
1029  }
1030  } else {
1031  $localizationArray = [];
1032  }
1033  return $localizationArray[$this->language];
1034  }
1035 
1041  protected function getJSToolbarArray()
1042  {
1043  // The toolbar array
1044  $toolbar = [];
1045  // The current row; a "linebreak" ends the current row
1046  $row = [];
1047  // The current group; each group is between "bar"s; a "linebreak" ends the current group
1048  $group = [];
1049  // Process each toolbar item in the toolbar order list
1050  foreach ($this->toolbarOrderArray as $item) {
1051  switch ($item) {
1052  case 'linebreak':
1053  // Add row to toolbar if not empty
1054  if (!empty($group)) {
1055  $row[] = $group;
1056  $group = [];
1057  }
1058  if (!empty($row)) {
1059  $toolbar[] = $row;
1060  $row = [];
1061  }
1062  break;
1063  case 'bar':
1064  // Add group to row if not empty
1065  if (!empty($group)) {
1066  $row[] = $group;
1067  $group = [];
1068  }
1069  break;
1070  case 'space':
1071  if (end($group) != $this->convertToolbarForHtmlAreaArray[$item]) {
1072  $group[] = $this->convertToolbarForHtmlAreaArray[$item];
1073  }
1074  break;
1075  default:
1076  if (in_array($item, $this->toolbar)) {
1077  // Add the item to the group
1078  $convertedItem = $this->convertToolbarForHtmlAreaArray[$item];
1079  if ($convertedItem) {
1080  $group[] = $convertedItem;
1081  }
1082  }
1083  }
1084  }
1085  // Add the last group and last line, if not empty
1086  if (!empty($group)) {
1087  $row[] = $group;
1088  }
1089  if (!empty($row)) {
1090  $toolbar[] = $row;
1091  }
1092  return json_encode($toolbar);
1093  }
1094 
1101  protected function getFullFileName($filename)
1102  {
1103  if (substr($filename, 0, 4) === 'EXT:') {
1104  // extension
1105  list($extKey, $local) = explode('/', substr($filename, 4), 2);
1106  $newFilename = '';
1107  if ((string)$extKey !== '' && ExtensionManagementUtility::isLoaded($extKey) && (string)$local !== '') {
1108  $newFilename = ($this->isFrontendEditActive()
1111  . $local;
1112  }
1113  } else {
1114  $path = ($this->isFrontendEditActive() ? '' : '../');
1115  $newFilename = $path . ($filename[0] === '/' ? substr($filename, 1) : $filename);
1116  }
1117  return GeneralUtility::resolveBackPath($newFilename);
1118  }
1119 
1125  protected function addOnSubmitJavaScriptCode()
1126  {
1127  $onSubmitCode = [];
1128  $onSubmitCode[] = 'if (RTEarea[' . GeneralUtility::quoteJSvalue($this->domIdentifier) . ']) {';
1129  $onSubmitCode[] = 'document.editform[' . GeneralUtility::quoteJSvalue($this->data['parameterArray']['itemFormElName']) . '].value = RTEarea[' . GeneralUtility::quoteJSvalue($this->domIdentifier) . '].editor.getHTML();';
1130  $onSubmitCode[] = '} else {';
1131  $onSubmitCode[] = 'OK = 0;';
1132  $onSubmitCode[] = '};';
1133  $this->resultArray['additionalJavaScriptSubmit'][] = implode(LF, $onSubmitCode);
1134  }
1135 
1141  protected function isFrontendEditActive()
1142  {
1143  return is_object($GLOBALS['TSFE']) && $GLOBALS['TSFE']->beUserLogin && $GLOBALS['BE_USER']->frontendEdit instanceof FrontendEditingController;
1144  }
1145 
1151  protected function clientInfo()
1152  {
1153  $userAgent = GeneralUtility::getIndpEnv('HTTP_USER_AGENT');
1154  $browserInfo = ClientUtility::getBrowserInfo($userAgent);
1155  // Known engines: order is not irrelevant!
1156  $knownEngines = ['opera', 'msie', 'gecko', 'webkit'];
1157  if (is_array($browserInfo['all'])) {
1158  foreach ($knownEngines as $engine) {
1159  if ($browserInfo['all'][$engine]) {
1160  $browserInfo['browser'] = $engine;
1161  $browserInfo['version'] = ClientUtility::getVersion($browserInfo['all'][$engine]);
1162  break;
1163  }
1164  }
1165  }
1166  return $browserInfo;
1167  }
1168 
1174  public function initializeLanguageRelatedProperties()
1175  {
1176  $database = $this->getDatabaseConnection();
1177  $this->language = $GLOBALS['LANG']->lang;
1178  if ($this->language === 'default' || !$this->language) {
1179  $this->language = 'en';
1180  }
1181  $currentLanguageUid = $this->data['databaseRow']['sys_language_uid'];
1182  if (is_array($currentLanguageUid)) {
1183  $currentLanguageUid = $currentLanguageUid[0];
1184  }
1185  $this->contentLanguageUid = (int)max($currentLanguageUid, 0);
1186  if ($this->contentLanguageUid) {
1187  $this->contentISOLanguage = $this->language;
1188  if (ExtensionManagementUtility::isLoaded('static_info_tables')) {
1189  $tableA = 'sys_language';
1190  $tableB = 'static_languages';
1191  $selectFields = $tableA . '.uid,' . $tableB . '.lg_iso_2,' . $tableB . '.lg_country_iso_2';
1192  $tableAB = $tableA . ' LEFT JOIN ' . $tableB . ' ON ' . $tableA . '.static_lang_isocode=' . $tableB . '.uid';
1193  $whereClause = $tableA . '.uid = ' . intval($this->contentLanguageUid);
1194  $whereClause .= BackendUtility::BEenableFields($tableA);
1195  $whereClause .= BackendUtility::deleteClause($tableA);
1196  $res = $database->exec_SELECTquery($selectFields, $tableAB, $whereClause);
1197  while ($languageRow = $database->sql_fetch_assoc($res)) {
1198  $this->contentISOLanguage = strtolower(trim($languageRow['lg_iso_2']) . (trim($languageRow['lg_country_iso_2']) ? '_' . trim($languageRow['lg_country_iso_2']) : ''));
1199  }
1200  $database->sql_free_result($res);
1201  }
1202  } else {
1203  $this->contentISOLanguage = trim($this->processedRteConfiguration['defaultContentLanguage']) ?: 'en';
1204  $languageCodeParts = explode('_', $this->contentISOLanguage);
1205  $this->contentISOLanguage = strtolower($languageCodeParts[0]) . ($languageCodeParts[1] ? '_' . strtoupper($languageCodeParts[1]) : '');
1206  // Find the configured language in the list of localization locales
1208  $locales = GeneralUtility::makeInstance(Locales::class);
1209  // If not found, default to 'en'
1210  if (!in_array($this->contentISOLanguage, $locales->getLocales())) {
1211  $this->contentISOLanguage = 'en';
1212  }
1213  }
1214  $this->contentTypo3Language = $this->contentISOLanguage === 'en' ? 'default' : $this->contentISOLanguage;
1215  }
1216 
1225  protected function logDeprecatedProperty($deprecatedProperty, $useProperty, $version)
1226  {
1227  $backendUser = $this->getBackendUserAuthentication();
1228  if (!$this->processedRteConfiguration['logDeprecatedProperties.']['disabled']) {
1229  $message = sprintf(
1230  '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.',
1231  $deprecatedProperty,
1232  $useProperty,
1233  $version,
1234  $this->data['databaseRow']['pid']
1235  );
1237  if ($this->processedRteConfiguration['logDeprecatedProperties.']['logAlsoToBELog']) {
1238  $message = sprintf(
1239  $this->getLanguageService()->sL('LLL:EXT:rtehtmlarea/Resources/Private/Language/locallang.xlf:deprecatedPropertyMessage'),
1240  $deprecatedProperty,
1241  $useProperty,
1242  $version,
1243  $this->data['databaseRow']['pid']
1244  );
1245  $backendUser->simplelog($message, 'rtehtmlarea');
1246  }
1247  }
1248  }
1249 
1255  protected function RTEtsConfigParams()
1256  {
1257  $parameters = BackendUtility::getSpecConfParametersFromArray($this->defaultExtras['rte_transform']['parameters']);
1258  $result = [
1259  $this->data['tableName'],
1260  $this->data['databaseRow']['uid'],
1261  $this->data['fieldName'],
1263  $this->data['recordTypeValue'],
1265  $parameters['imgpath'],
1266  ];
1267  return implode(':', $result);
1268  }
1269 
1276  protected function cleanList($str)
1277  {
1278  if (strstr($str, '*')) {
1279  $str = '*';
1280  } else {
1281  $str = implode(',', array_unique(GeneralUtility::trimExplode(',', $str, true)));
1282  }
1283  return $str;
1284  }
1285 
1292  protected function transformDatabaseContentToEditor($value)
1293  {
1294  // change <strong> to <b>
1295  $value = preg_replace('/<(\\/?)strong/i', '<$1b', $value);
1296  // change <em> to <i>
1297  $value = preg_replace('/<(\\/?)em([^b>]*>)/i', '<$1i$2', $value);
1298 
1299  if ($this->defaultExtras['rte_transform']) {
1300  $parameters = BackendUtility::getSpecConfParametersFromArray($this->defaultExtras['rte_transform']['parameters']);
1301  // There must be a mode set for transformation
1302  if ($parameters['mode']) {
1304  $parseHTML = GeneralUtility::makeInstance(RteHtmlParser::class);
1305  $parseHTML->init($this->data['table'] . ':' . $this->data['fieldName'], $this->pidOfVersionedMotherRecord);
1306  $parseHTML->setRelPath('');
1307  $value = $parseHTML->RTE_transform($value, $this->defaultExtras, 'rte', $this->processedRteConfiguration);
1308  }
1309  }
1310  return $value;
1311  }
1312 
1318  protected function isInFullScreenMode()
1319  {
1320  return GeneralUtility::_GP('route') === '/wizard/rte';
1321  }
1322 
1326  protected function getLanguageService()
1327  {
1328  return $GLOBALS['LANG'];
1329  }
1330 
1334  protected function getBackendUserAuthentication()
1335  {
1336  return $GLOBALS['BE_USER'];
1337  }
1338 
1342  protected function getDatabaseConnection()
1343  {
1344  return $GLOBALS['TYPO3_DB'];
1345  }
1346 }
static minifyJavaScript($script, &$error='')
static getPagesTSconfig($id, $rootLine=null, $returnPartArray=false)
hasCircularDependency(&$classesArray, $requiringClass, $initialClass, $recursionLevel=0)
$database
Definition: server.php:40
static writeFileToTypo3tempDir($filepath, $content)
static BEenableFields($table, $inv=false)
logDeprecatedProperty($deprecatedProperty, $useProperty, $version)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static fixVersioningPid($table, &$rr, $ignoreWorkspaceMatch=false)
getValidationDataAsDataAttribute(array $config)
writeTemporaryFile($label, $fileExtension='js', $contents='')
static RTEsetup($RTEprop, $table, $field, $type='')
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
static getFileAbsFileName($filename, $onlyRelative=true, $relToTYPO3_mainDir=false)
static getSpecConfParts($defaultExtrasString, $_='')
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
$locales
Definition: be_users.php:6
static deleteClause($table, $tableAlias='')