/**
  * Returns RichTextElement as class name if RTE widget should be rendered.
  *
  * @return string|void New class name or void if this resolver does not change current class name.
  */
 public function resolve()
 {
     $table = $this->data['tableName'];
     $fieldName = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $backendUser = $this->getBackendUserAuthentication();
     if (!$parameterArray['fieldConf']['config']['readOnly'] && $backendUser->isRTE()) {
         // @todo: Most of this stuff is prepared by data providers within $this->data already
         $specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
         // If "richtext" is within defaultExtras
         if (isset($specialConfiguration['richtext'])) {
             // Operates by reference on $row! 'pid' is changed ...
             BackendUtility::fixVersioningPid($table, $row);
             list($recordPid, $tsConfigPid) = BackendUtility::getTSCpidCached($table, $row['uid'], $row['pid']);
             // If the pid-value is not negative (that is, a pid could NOT be fetched)
             if ($tsConfigPid >= 0) {
                 // Fetch page ts config and do some magic with it to find out if RTE is disabled on TS level.
                 $rteSetup = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
                 $rteTcaTypeValue = $this->data['recordTypeValue'];
                 $rteSetupConfiguration = BackendUtility::RTEsetup($rteSetup['properties'], $table, $fieldName, $rteTcaTypeValue);
                 if (!$rteSetupConfiguration['disabled']) {
                     // Finally, we're sure the editor should really be rendered ...
                     return RichtextElement::class;
                 }
             }
         }
     }
     return null;
 }
Пример #2
0
	/**
	 * Returns RichTextElement as class name if RTE widget should be rendered.
	 *
	 * @return string|void New class name or void if this resolver does not change current class name.
	 */
	public function resolve() {
		$table = $this->globalOptions['table'];
		$fieldName = $this->globalOptions['fieldName'];
		$row = $this->globalOptions['databaseRow'];
		$parameterArray = $this->globalOptions['parameterArray'];
		$backendUser = $this->getBackendUserAuthentication();

		if (
			// Whole thing is not read only
			empty($this->globalOptions['renderReadonly'])
			// This field is not read only
			&& !$parameterArray['fieldConf']['config']['readOnly']
			// If RTE is generally enabled by user settings and RTE object registry can return something valid
			&& $backendUser->isRTE()
		) {
			$specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
			// $parameters is a key=>value array from "defaultExtras" pipe separated rte_transform string
			$parameters = BackendUtility::getSpecConfParametersFromArray($specialConfiguration['rte_transform']['parameters']);

			if (
				// If "richtext" is within defaultExtras
				isset($specialConfiguration['richtext'])
				// rte_transform[flag=foo] means RTE should only be rendered if the value of db row field "foo" can be interpreted as TRUE
				&& (!$parameters['flag'] || !$row[$parameters['flag']])
			) {
				// Operates by reference on $row! 'pid' is changed ...
				BackendUtility::fixVersioningPid($table, $row);
				list($recordPid, $tsConfigPid) = BackendUtility::getTSCpidCached($table, $row['uid'], $row['pid']);
				// If the pid-value is not negative (that is, a pid could NOT be fetched)
				if ($tsConfigPid >= 0) {
					// Fetch page ts config and do some magic with it to find out if RTE is disabled on TS level.
					$rteSetup = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
					$rteTcaTypeValue = BackendUtility::getTCAtypeValue($table, $row);
					$rteSetupConfiguration = BackendUtility::RTEsetup($rteSetup['properties'], $table, $fieldName, $rteTcaTypeValue);
					if (!$rteSetupConfiguration['disabled']) {
						// Finally, we're sure the editor should really be rendered ...
						return RichtextElement::class;
					}
				}
			}
		}
		return NULL;
	}
Пример #3
0
 /**
  * Renders the ckeditor element
  *
  * @return array
  * @throws \InvalidArgumentException
  */
 public function render() : array
 {
     $resultArray = $this->initializeResultArray();
     $row = $this->data['databaseRow'];
     BackendUtility::fixVersioningPid($this->data['tableName'], $row);
     $this->pidOfVersionedMotherRecord = (int) $row['pid'];
     $resourcesPath = PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::extPath('rte_ckeditor', 'Resources/Public/'));
     $table = $this->data['tableName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $defaultExtras = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     BackendUtility::fixVersioningPid($table, $row);
     $fieldId = $this->sanitizeFieldId($parameterArray['itemFormElName']);
     $resultArray['html'] = $this->renderWizards([$this->getHtml($fieldId)], $parameterArray['fieldConf']['config']['wizards'], $table, $row, $this->data['fieldName'], $parameterArray, $parameterArray['itemFormElName'], $defaultExtras, true);
     $vanillaRteTsConfig = $this->getBackendUserAuthentication()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($this->data['effectivePid']));
     $this->rteConfiguration = BackendUtility::RTEsetup($vanillaRteTsConfig['properties'], $table, $this->data['fieldName'], $this->data['recordTypeValue']);
     $resultArray['requireJsModules'] = [];
     $resultArray['requireJsModules'][] = ['ckeditor' => $this->getCkEditorRequireJsModuleCode($resourcesPath, $fieldId)];
     return $resultArray;
 }
Пример #4
0
 /**
  * This will render a <textarea> OR RTE area form field,
  * possibly with various control/validation features
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->globalOptions['table'];
     $fieldName = $this->globalOptions['fieldName'];
     $row = $this->globalOptions['databaseRow'];
     $parameterArray = $this->globalOptions['parameterArray'];
     $resultArray = $this->initializeResultArray();
     $backendUser = $this->getBackendUserAuthentication();
     $validationConfig = array();
     // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
     $specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     // Setting up the altItem form field, which is a hidden field containing the value
     $altItem = '<input type="hidden" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
     BackendUtility::fixVersioningPid($table, $row);
     list($recordPid, $tsConfigPid) = BackendUtility::getTSCpidCached($table, $row['uid'], $row['pid']);
     // If the pid-value is not negative (that is, a pid could NOT be fetched)
     $rteSetup = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
     $rteTcaTypeValue = BackendUtility::getTCAtypeValue($table, $row);
     $rteSetupConfiguration = BackendUtility::RTEsetup($rteSetup['properties'], $table, $fieldName, $rteTcaTypeValue);
     // Get RTE object, draw form and set flag:
     $rteObject = BackendUtility::RTEgetObj();
     $dummyFormEngine = new FormEngine();
     $rteResult = $rteObject->drawRTE($dummyFormEngine, $table, $fieldName, $row, $parameterArray, $specialConfiguration, $rteSetupConfiguration, $rteTcaTypeValue, '', $tsConfigPid, $this->globalOptions, $this->initializeResultArray(), $this->getValidationDataAsDataAttribute($validationConfig));
     // This is a compat layer for "other" RTE's: If the result is not an array, it is the html string,
     // otherwise it is a structure similar to our casual return array
     // @todo: This interface needs a full re-definition, RTE should probably be its own type in the
     // @todo: end, and other RTE implementations could then just override this.
     if (is_array($rteResult)) {
         $html = $rteResult['html'];
         $rteResult['html'] = '';
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $rteResult);
     } else {
         $html = $rteResult;
     }
     // Wizard
     $html = $this->renderWizards(array($html, $altItem), $parameterArray['fieldConf']['config']['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specialConfiguration, TRUE);
     $resultArray['html'] = $html;
     return $resultArray;
 }
Пример #5
0
 /**
  * @param ServerRequestInterface $request
  */
 protected function initVariables(ServerRequestInterface $request)
 {
     parent::initVariables($request);
     $queryParameters = $request->getQueryParams();
     $this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
     $this->currentLinkParts['currentImage'] = !empty($queryParameters['fileUid']) ? $queryParameters['fileUid'] : 0;
     // Process bparams
     $pArr = explode('|', $this->bparams);
     $pRteArr = explode(':', $pArr[1]);
     $this->editorNo = $pRteArr[0];
     $this->contentTypo3Language = $pRteArr[1];
     $this->RTEtsConfigParams = $pArr[2];
     if (!$this->editorNo) {
         $this->editorNo = GeneralUtility::_GP('editorNo');
         $this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
         $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
     }
     $pArr[1] = implode(':', [$this->editorNo, $this->contentTypo3Language]);
     $pArr[2] = $this->RTEtsConfigParams;
     $pArr[3] = $this->displayedLinkHandlerId === 'plain' ? self::PLAIN_MODE_IMAGE_FILE_EXTENSIONS : '';
     $this->bparams = implode('|', $pArr);
     $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
     $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
     $this->RTEProperties = $RTEsetup['properties'];
     $thisConfig = BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
     $this->buttonConfig = isset($thisConfig['buttons.']['image.']) ? $thisConfig['buttons.']['image.'] : [];
 }
Пример #6
0
 /**
  * Processing of the sheet/language data array
  * When it finds a field with a value the processing is done by ->checkValue_SW() by default but if a call back function name is given that method in this class will be called for the processing instead.
  *
  * @param array $dataValues New values (those being processed): Multidimensional Data array for sheet/language, passed by reference!
  * @param array $dataValues_current Current values: Multidimensional Data array. May be empty array() if not needed (for callBackFunctions)
  * @param array $uploadedFiles Uploaded files array for sheet/language. May be empty array() if not needed (for callBackFunctions)
  * @param array $DSelements Data structure which fits the data array
  * @param array $pParams A set of parameters to pass through for the calling of the evaluation functions / call back function
  * @param string $callBackFunc Call back function, default is checkValue_SW(). If $this->callBackObj is set to an object, the callback function in that object is called instead.
  * @param string $structurePath
  * @return void
  * @see checkValue_flex_procInData()
  */
 public function checkValue_flex_procInData_travDS(&$dataValues, $dataValues_current, $uploadedFiles, $DSelements, $pParams, $callBackFunc, $structurePath)
 {
     if (!is_array($DSelements)) {
         return;
     }
     // For each DS element:
     foreach ($DSelements as $key => $dsConf) {
         // Array/Section:
         if ($DSelements[$key]['type'] == 'array') {
             if (!is_array($dataValues[$key]['el'])) {
                 continue;
             }
             if ($DSelements[$key]['section']) {
                 $newIndexCounter = 0;
                 foreach ($dataValues[$key]['el'] as $ik => $el) {
                     if (!is_array($el)) {
                         continue;
                     }
                     if (!is_array($dataValues_current[$key]['el'])) {
                         $dataValues_current[$key]['el'] = array();
                     }
                     $theKey = key($el);
                     if (!is_array($dataValues[$key]['el'][$ik][$theKey]['el'])) {
                         continue;
                     }
                     $this->checkValue_flex_procInData_travDS($dataValues[$key]['el'][$ik][$theKey]['el'], is_array($dataValues_current[$key]['el'][$ik]) ? $dataValues_current[$key]['el'][$ik][$theKey]['el'] : array(), $uploadedFiles[$key]['el'][$ik][$theKey]['el'], $DSelements[$key]['el'][$theKey]['el'], $pParams, $callBackFunc, $structurePath . $key . '/el/' . $ik . '/' . $theKey . '/el/');
                     // If element is added dynamically in the flexform of TCEforms, we map the ID-string to the next numerical index we can have in that particular section of elements:
                     // The fact that the order changes is not important since order is controlled by a separately submitted index.
                     if (substr($ik, 0, 3) == 'ID-') {
                         $newIndexCounter++;
                         // Set mapping index
                         $this->newIndexMap[$ik] = (is_array($dataValues_current[$key]['el']) && !empty($dataValues_current[$key]['el']) ? max(array_keys($dataValues_current[$key]['el'])) : 0) + $newIndexCounter;
                         // Transfer values
                         $dataValues[$key]['el'][$this->newIndexMap[$ik]] = $dataValues[$key]['el'][$ik];
                         // Unset original
                         unset($dataValues[$key]['el'][$ik]);
                     }
                 }
             } else {
                 if (!isset($dataValues[$key]['el'])) {
                     $dataValues[$key]['el'] = array();
                 }
                 $this->checkValue_flex_procInData_travDS($dataValues[$key]['el'], $dataValues_current[$key]['el'], $uploadedFiles[$key]['el'], $DSelements[$key]['el'], $pParams, $callBackFunc, $structurePath . $key . '/el/');
             }
         } else {
             if (!is_array($dsConf['TCEforms']['config']) || !is_array($dataValues[$key])) {
                 continue;
             }
             foreach ($dataValues[$key] as $vKey => $data) {
                 if ($callBackFunc) {
                     if (is_object($this->callBackObj)) {
                         $res = $this->callBackObj->{$callBackFunc}($pParams, $dsConf['TCEforms']['config'], $dataValues[$key][$vKey], $dataValues_current[$key][$vKey], $uploadedFiles[$key][$vKey], $structurePath . $key . '/' . $vKey . '/');
                     } else {
                         $res = $this->{$callBackFunc}($pParams, $dsConf['TCEforms']['config'], $dataValues[$key][$vKey], $dataValues_current[$key][$vKey], $uploadedFiles[$key][$vKey], $structurePath . $key . '/' . $vKey . '/');
                     }
                 } else {
                     // Default
                     list($CVtable, $CVid, $CVcurValue, $CVstatus, $CVrealPid, $CVrecFID, $CVtscPID) = $pParams;
                     $additionalData = array('flexFormId' => $CVrecFID, 'flexFormPath' => trim(rtrim($structurePath, '/') . '/' . $key . '/' . $vKey, '/'));
                     $res = $this->checkValue_SW(array(), $dataValues[$key][$vKey], $dsConf['TCEforms']['config'], $CVtable, $CVid, $dataValues_current[$key][$vKey], $CVstatus, $CVrealPid, $CVrecFID, '', $uploadedFiles[$key][$vKey], $CVtscPID, $additionalData);
                     // Look for RTE transformation of field:
                     if ($dataValues[$key]['_TRANSFORM_' . $vKey] == 'RTE' && !$this->dontProcessTransformations) {
                         // Unsetting trigger field - we absolutely don't want that into the data storage!
                         unset($dataValues[$key]['_TRANSFORM_' . $vKey]);
                         if (isset($res['value'])) {
                             // Calculating/Retrieving some values here:
                             list(, , $recFieldName) = explode(':', $CVrecFID);
                             $theTypeString = BackendUtility::getTCAtypeValue($CVtable, $this->checkValue_currentRecord);
                             $specConf = BackendUtility::getSpecConfParts($dsConf['TCEforms']['defaultExtras']);
                             // Find, thisConfig:
                             $RTEsetup = $this->BE_USER->getTSConfig('RTE', BackendUtility::getPagesTSconfig($CVtscPID));
                             $thisConfig = BackendUtility::RTEsetup($RTEsetup['properties'], $CVtable, $recFieldName, $theTypeString);
                             $res['value'] = $this->transformRichtextContentToDatabase($res['value'], $CVtable, $recFieldName, $specConf, $thisConfig, $CVrealPid);
                         }
                     }
                 }
                 // Adding the value:
                 if (isset($res['value'])) {
                     $dataValues[$key][$vKey] = $res['value'];
                 }
                 // Finally, check if new and old values are different (or no .vDEFbase value is found) and if so, we record the vDEF value for diff'ing.
                 // We do this after $dataValues has been updated since I expect that $dataValues_current holds evaluated values from database (so this must be the right value to compare with).
                 if (substr($vKey, -9) != '.vDEFbase') {
                     // @deprecated: flexFormXMLincludeDiffBase is only enabled by ext:compatibility6 since TYPO3 CMS 7, vDEFbase can be unset / ignored with TYPO3 CMS 8
                     if ($this->clear_flexFormData_vDEFbase) {
                         $dataValues[$key][$vKey . '.vDEFbase'] = '';
                     } elseif ($this->updateModeL10NdiffData && $GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && $vKey !== 'vDEF' && ((string) $dataValues[$key][$vKey] !== (string) $dataValues_current[$key][$vKey] || !isset($dataValues_current[$key][$vKey . '.vDEFbase']) || $this->updateModeL10NdiffData === 'FORCE_FFUPD')) {
                         // Now, check if a vDEF value is submitted in the input data, if so we expect this has been processed prior to this operation (normally the case since those fields are higher in the form) and we can use that:
                         if (isset($dataValues[$key]['vDEF'])) {
                             $diffValue = $dataValues[$key]['vDEF'];
                         } else {
                             // If not found (for translators with no access to the default language) we use the one from the current-value data set:
                             $diffValue = $dataValues_current[$key]['vDEF'];
                         }
                         // Setting the reference value for vDEF for this translation. This will be used for translation tools to make a diff between the vDEF and vDEFbase to see if an update would be fitting.
                         $dataValues[$key][$vKey . '.vDEFbase'] = $this->updateModeL10NdiffDataClear ? '' : $diffValue;
                     }
                 }
             }
         }
     }
 }
Пример #7
0
 /**
  * Checking if the RTE is available/enabled for a certain table/field and if so, it returns TRUE.
  * Used to determine if the RTE button should be displayed.
  *
  * @param string $table Table name
  * @param array $row Record row (needed, if there are RTE dependencies based on other fields in the record)
  * @param string $field Field name
  * @return boolean Returns TRUE if the rich text editor would be enabled/available for the field name specified.
  * @todo Define visibility
  */
 public function isRTEforField($table, $row, $field)
 {
     $specConf = $this->getSpecConfForField($table, $row, $field);
     if (!count($specConf)) {
         return FALSE;
     }
     $p = BackendUtility::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']);
     if (isset($specConf['richtext']) && (!$p['flag'] || !$row[$p['flag']])) {
         BackendUtility::fixVersioningPid($table, $row);
         list($tscPID, $thePidValue) = BackendUtility::getTSCpid($table, $row['uid'], $row['pid']);
         // If the pid-value is not negative (that is, a pid could NOT be fetched)
         if ($thePidValue >= 0) {
             if (!isset($this->rteSetup[$tscPID])) {
                 $this->rteSetup[$tscPID] = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($tscPID));
             }
             $RTEtypeVal = BackendUtility::getTCAtypeValue($table, $row);
             $thisConfig = BackendUtility::RTEsetup($this->rteSetup[$tscPID]['properties'], $table, $field, $RTEtypeVal);
             if (!$thisConfig['disabled']) {
                 return TRUE;
             }
         }
     }
     return FALSE;
 }
Пример #8
0
 /**
  * @param ServerRequestInterface $request
  */
 protected function initVariables(ServerRequestInterface $request)
 {
     parent::initVariables($request);
     $parameters = $request->getQueryParams();
     $this->bparams = isset($parameters['bparams']) ? $parameters['bparams'] : '';
     // Process bparams
     $pArr = explode('|', $this->bparams);
     $pRteArr = explode(':', $pArr[1]);
     $this->editorNo = $pRteArr[0];
     $this->contentTypo3Language = $pRteArr[1];
     $this->RTEtsConfigParams = $pArr[2];
     if (!$this->editorNo) {
         $this->editorNo = GeneralUtility::_GP('editorNo');
         $this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
         $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
     }
     $pArr[1] = implode(':', array($this->editorNo, $this->contentTypo3Language));
     $pArr[2] = $this->RTEtsConfigParams;
     $this->bparams = implode('|', $pArr);
     $this->contentLanguageService->init($this->contentTypo3Language);
     $this->buttonConfig = isset($this->RTEProperties['default.']['buttons.']['link.']) ? $this->RTEProperties['default.']['buttons.']['link.'] : [];
     $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
     $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
     $this->thisConfig = BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
 }
Пример #9
0
 /**
  * Get the RTE configuration from Page TSConfig
  *
  * @return array RTE configuration array
  */
 protected function getRTEConfig()
 {
     $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
     $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
     return BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
 }
Пример #10
0
 /**
  * Get the RTE configuration from Page TSConfig
  *
  * @return array[] RTE configuration array
  */
 protected function getRTEConfig()
 {
     $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
     $RTEsetup = $this->getBackendUserAuthentication()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
     return BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
 }
Пример #11
0
 /**
  * Rich Text Editor (RTE) html parser
  *
  * @param 	[type]		$openKeys: ...
  * @return 	[type]		...
  * @todo Define visibility
  */
 public function main_parse_html($openKeys)
 {
     global $TYPO3_CONF_VARS;
     $editorNo = GeneralUtility::_GP('editorNo');
     $html = GeneralUtility::_GP('content');
     $RTEtsConfigParts = explode(':', GeneralUtility::_GP('RTEtsConfigParams'));
     $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
     $thisConfig = \TYPO3\CMS\Backend\Utility\BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
     $HTMLParser = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Html\\HtmlParser');
     if (is_array($thisConfig['enableWordClean.'])) {
         $HTMLparserConfig = $thisConfig['enableWordClean.']['HTMLparser.'];
         if (is_array($HTMLparserConfig)) {
             $this->keepSpanTagsWithId($HTMLparserConfig);
             $HTMLparserConfig = $HTMLParser->HTMLparserConfig($HTMLparserConfig);
         }
     }
     if (is_array($HTMLparserConfig)) {
         $html = $HTMLParser->HTMLcleaner($html, $HTMLparserConfig[0], $HTMLparserConfig[1], $HTMLparserConfig[2], $HTMLparserConfig[3]);
     }
     if (is_array($TYPO3_CONF_VARS['EXTCONF'][$this->extKey][$this->prefixId]['cleanPastedContent'])) {
         foreach ($TYPO3_CONF_VARS['EXTCONF'][$this->extKey][$this->prefixId]['cleanPastedContent'] as $classRef) {
             $hookObj = GeneralUtility::getUserObj($classRef);
             if (method_exists($hookObj, 'cleanPastedContent_afterCleanWord')) {
                 $html = $hookObj->cleanPastedContent_afterCleanWord($html, $thisConfig);
             }
         }
     }
     return $html;
 }
Пример #12
0
    /**
     * Constructor:
     * Initializes a lot of variables, setting JavaScript functions in header etc.
     *
     * @return void
     * @todo Define visibility
     */
    public function init()
    {
        // Main GPvars:
        $this->pointer = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('pointer');
        $this->bparams = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('bparams');
        $this->P = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('P');
        $this->RTEtsConfigParams = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('RTEtsConfigParams');
        $this->expandPage = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('expandPage');
        $this->expandFolder = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('expandFolder');
        $this->PM = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('PM');
        // Find "mode"
        $this->mode = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('mode');
        if (!$this->mode) {
            $this->mode = 'rte';
        }
        // Creating backend template object:
        $this->doc = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Template\\DocumentTemplate');
        $this->doc->backPath = $GLOBALS['BACK_PATH'];
        // Load the Prototype library and browse_links.js
        $this->doc->getPageRenderer()->loadPrototype();
        $this->doc->loadJavascriptLib('js/browse_links.js');
        $this->doc->loadJavascriptLib('js/tree.js');
        // init hook objects:
        $this->hookObjects = array();
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['browseLinksHook'])) {
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['browseLinksHook'] as $classData) {
                $processObject = \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($classData);
                if (!$processObject instanceof \TYPO3\CMS\Core\ElementBrowser\ElementBrowserHookInterface) {
                    throw new \UnexpectedValueException('$processObject must implement interface TYPO3\\CMS\\Core\\ElementBrowser\\ElementBrowserHookInterface', 1195039394);
                }
                $parameters = array();
                $processObject->init($this, $parameters);
                $this->hookObjects[] = $processObject;
            }
        }
        // Site URL
        // Current site url
        $this->siteURL = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
        // The script to link to
        $this->thisScript = \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('SCRIPT_NAME');
        // Init fileProcessor
        $this->fileProcessor = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Utility\\File\\BasicFileUtility');
        $this->fileProcessor->init($GLOBALS['FILEMOUNTS'], $GLOBALS['TYPO3_CONF_VARS']['BE']['fileExtensions']);
        // CurrentUrl - the current link url must be passed around if it exists
        if ($this->mode == 'wizard') {
            $currentValues = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(LF, trim($this->P['currentValue']));
            if (count($currentValues) > 0) {
                $currentValue = array_pop($currentValues);
            } else {
                $currentValue = '';
            }
            $currentLinkParts = \TYPO3\CMS\Core\Utility\GeneralUtility::unQuoteFilenames($currentValue, TRUE);
            $initialCurUrlArray = array('href' => $currentLinkParts[0], 'target' => $currentLinkParts[1], 'class' => $currentLinkParts[2], 'title' => $currentLinkParts[3], 'params' => $currentLinkParts[4]);
            $this->curUrlArray = is_array(\TYPO3\CMS\Core\Utility\GeneralUtility::_GP('curUrl')) ? array_merge($initialCurUrlArray, \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('curUrl')) : $initialCurUrlArray;
            // Additional fields for page links
            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray'])) {
                $_params = array('conf' => &$conf, 'linkParts' => $currentLinkParts);
                foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendUrlArray'] as $objRef) {
                    $processor =& \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($objRef);
                    $processor->extendUrlArray($_params, $this);
                }
            }
            $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL);
            // pageid == 0 means that this is not an internal (page) link
            if ($this->curUrlInfo['pageid'] == 0 && $this->curUrlArray['href']) {
                // Check if there is the FAL API
                if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], 'file:')) {
                    $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
                    // Remove the "file:" prefix
                    $currentLinkParts[0] = rawurldecode(substr($this->curUrlArray['href'], 5));
                } elseif (file_exists(PATH_site . rawurldecode($this->curUrlArray['href']))) {
                    if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], PATH_site)) {
                        $currentLinkParts[0] = substr($this->curUrlArray['href'], strlen(PATH_site));
                    }
                    $this->curUrlInfo = $this->parseCurUrl($this->siteURL . $this->curUrlArray['href'], $this->siteURL);
                } elseif (strstr($this->curUrlArray['href'], '@')) {
                    // check for email link
                    if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($this->curUrlArray['href'], 'mailto:')) {
                        $currentLinkParts[0] = substr($this->curUrlArray['href'], 7);
                    }
                    $this->curUrlInfo = $this->parseCurUrl('mailto:' . $this->curUrlArray['href'], $this->siteURL);
                } else {
                    // nothing of the above. this is an external link
                    if (strpos($this->curUrlArray['href'], '://') === FALSE) {
                        $currentLinkParts[0] = 'http://' . $this->curUrlArray['href'];
                    }
                    $this->curUrlInfo = $this->parseCurUrl($currentLinkParts[0], $this->siteURL);
                }
            } elseif (!$this->curUrlArray['href']) {
                $this->curUrlInfo = array();
                $this->act = 'page';
            } else {
                $this->curUrlInfo = $this->parseCurUrl($this->siteURL . '?id=' . $this->curUrlArray['href'], $this->siteURL);
            }
        } else {
            $this->curUrlArray = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('curUrl');
            if ($this->curUrlArray['all']) {
                $this->curUrlArray = \TYPO3\CMS\Core\Utility\GeneralUtility::get_tag_attributes($this->curUrlArray['all']);
            }
            $this->curUrlInfo = $this->parseCurUrl($this->curUrlArray['href'], $this->siteURL);
        }
        // Determine nature of current url:
        $this->act = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('act');
        if (!$this->act) {
            $this->act = $this->curUrlInfo['act'];
        }
        // Rich Text Editor specific configuration:
        $addPassOnParams = '';
        if ((string) $this->mode == 'rte') {
            $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
            $addPassOnParams .= '&RTEtsConfigParams=' . rawurlencode($this->RTEtsConfigParams);
            $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
            $this->thisConfig = \TYPO3\CMS\Backend\Utility\BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
        }
        // Initializing the target value (RTE)
        $this->setTarget = $this->curUrlArray['target'] != '-' ? rawurlencode($this->curUrlArray['target']) : '';
        if ($this->thisConfig['defaultLinkTarget'] && !isset($this->curUrlArray['target'])) {
            $this->setTarget = $this->thisConfig['defaultLinkTarget'];
        }
        // Initializing the class value (RTE)
        $this->setClass = $this->curUrlArray['class'] != '-' ? rawurlencode($this->curUrlArray['class']) : '';
        // Initializing the title value (RTE)
        $this->setTitle = $this->curUrlArray['title'] != '-' ? rawurlencode($this->curUrlArray['title']) : '';
        // Initializing the params value
        $this->setParams = $this->curUrlArray['params'] != '-' ? rawurlencode($this->curUrlArray['params']) : '';
        // BEGIN accumulation of header JavaScript:
        $JScode = '
				// This JavaScript is primarily for RTE/Link. jumpToUrl is used in the other cases as well...
			var add_href="' . ($this->curUrlArray['href'] ? '&curUrl[href]=' . rawurlencode($this->curUrlArray['href']) : '') . '";
			var add_target="' . ($this->setTarget ? '&curUrl[target]=' . rawurlencode($this->setTarget) : '') . '";
			var add_class="' . ($this->setClass ? '&curUrl[class]=' . rawurlencode($this->setClass) : '') . '";
			var add_title="' . ($this->setTitle ? '&curUrl[title]=' . rawurlencode($this->setTitle) : '') . '";
			var add_params="' . ($this->bparams ? '&bparams=' . rawurlencode($this->bparams) : '') . '";

			var cur_href="' . ($this->curUrlArray['href'] ? rawurlencode($this->curUrlArray['href']) : '') . '";
			var cur_target="' . ($this->setTarget ? $this->setTarget : '') . '";
			var cur_class = "' . ($this->setClass ? $this->setClass : '') . '";
			var cur_title="' . ($this->setTitle ? $this->setTitle : '') . '";
			var cur_params="' . ($this->setParams ? $this->setParams : '') . '";

			function browse_links_setTarget(target) {	//
				cur_target=target;
				add_target="&curUrl[target]="+escape(target);
			}
			function browse_links_setClass(cssClass) {   //
				cur_class = cssClass;
				add_class = "&curUrl[class]=" + escape(cssClass);
			}
			function browse_links_setTitle(title) {	//
				cur_title=title;
				add_title="&curUrl[title]="+escape(title);
			}
			function browse_links_setValue(value) {	//
				cur_href=value;
				add_href="&curUrl[href]="+value;
			}
			function browse_links_setParams(params) {	//
				cur_params=params;
				add_params="&curUrl[params]="+escape(params);
			}
		';
        // Functions used, if the link selector is in wizard mode (= TCEforms fields)
        if ($this->mode == 'wizard') {
            if (!$this->areFieldChangeFunctionsValid() && !$this->areFieldChangeFunctionsValid(TRUE)) {
                $this->P['fieldChangeFunc'] = array();
            }
            unset($this->P['fieldChangeFunc']['alert']);
            $update = '';
            foreach ($this->P['fieldChangeFunc'] as $k => $v) {
                $update .= '
				window.opener.' . $v;
            }
            $P2 = array();
            $P2['itemName'] = $this->P['itemName'];
            $P2['formName'] = $this->P['formName'];
            $P2['fieldChangeFunc'] = $this->P['fieldChangeFunc'];
            $P2['fieldChangeFuncHash'] = \TYPO3\CMS\Core\Utility\GeneralUtility::hmac(serialize($this->P['fieldChangeFunc']));
            $P2['params']['allowedExtensions'] = $this->P['params']['allowedExtensions'];
            $P2['params']['blindLinkOptions'] = $this->P['params']['blindLinkOptions'];
            $P2['params']['blindLinkFields'] = $this->P['params']['blindLinkFields'];
            $addPassOnParams .= \TYPO3\CMS\Core\Utility\GeneralUtility::implodeArrayForUrl('P', $P2);
            $JScode .= '
				function link_typo3Page(id,anchor) {	//
					updateValueInMainForm(id + (anchor ? anchor : ""));
					close();
					return false;
				}
				function link_folder(folder) {	//
					updateValueInMainForm(folder);
					close();
					return false;
				}
				function link_current() {	//
					if (cur_href!="http://" && cur_href!="mailto:") {
						returnBeforeCleaned = cur_href;
						if (returnBeforeCleaned.substr(0, 7) == "http://") {
							returnToMainFormValue = returnBeforeCleaned.substr(7);
						} else if (returnBeforeCleaned.substr(0, 7) == "mailto:") {
							if (returnBeforeCleaned.substr(0, 14) == "mailto:mailto:") {
								returnToMainFormValue = returnBeforeCleaned.substr(14);
							} else {
								returnToMainFormValue = returnBeforeCleaned.substr(7);
							}
						} else {
							returnToMainFormValue = returnBeforeCleaned;
						}
						updateValueInMainForm(returnToMainFormValue);
						close();
					}
					return false;
				}
				function checkReference() {	//
					if (window.opener && window.opener.document && window.opener.document.' . $this->P['formName'] . ' && window.opener.document.' . $this->P['formName'] . '["' . $this->P['itemName'] . '"] ) {
						return window.opener.document.' . $this->P['formName'] . '["' . $this->P['itemName'] . '"];
					} else {
						close();
					}
				}
				function updateValueInMainForm(input) {	//
					var field = checkReference();
					if (field) {
						if (cur_target == "" && (cur_class != "" || cur_title != "" || cur_params != "")) {
							cur_target = "-";
						}
						if (cur_class == "" && (cur_title != "" || cur_params != "")) {
							cur_class = "-";
						}
						cur_class = cur_class.replace(/[\'\\"]/g, "");
						if (cur_class.indexOf(" ") != -1) {
							cur_class = "\\"" + cur_class + "\\"";
						}
						if (cur_title == "" && cur_params != "") {
 							cur_title = "-";
 						}
						cur_title = cur_title.replace(/(^\\")|(\\"$)/g, "");
						if (cur_title.indexOf(" ") != -1) {
							cur_title = "\\"" + cur_title + "\\"";
						}
						if (cur_params) {
							cur_params = cur_params.replace(/\\bid\\=.*?(\\&|$)/, "");
						}
						input = input + " " + cur_target + " " + cur_class + " " + cur_title + " " + cur_params;
						if(field.value && field.className.search(/textarea/) != -1) {
							field.value += "\\n" + input;
						} else {
							field.value = input;
						}
						' . $update . '
					}
				}
			';
        } else {
            // Functions used, if the link selector is in RTE mode:
            $JScode .= '
				function link_typo3Page(id,anchor) {	//
					var theLink = \'' . $this->siteURL . '?id=\'+id+(anchor?anchor:"");
					self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title);
					return false;
				}
				function link_folder(folder) {	//
					var theLink = \'' . $this->siteURL . '\'+folder;
					self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title);
					return false;
				}
				function link_spec(theLink) {	//
					self.parent.parent.renderPopup_addLink(theLink, cur_target, cur_class, cur_title);
					return false;
				}
				function link_current() {	//
					if (cur_href!="http://" && cur_href!="mailto:") {
						self.parent.parent.renderPopup_addLink(cur_href, cur_target, cur_class, cur_title);
					}
					return false;
				}
			';
        }
        // General "jumpToUrl" function:
        $JScode .= '
			function jumpToUrl(URL,anchor) {	//
				var add_act = URL.indexOf("act=")==-1 ? "&act=' . $this->act . '" : "";
				var add_mode = URL.indexOf("mode=")==-1 ? "&mode=' . $this->mode . '" : "";
				var theLocation = URL + add_act + add_mode + add_href + add_target + add_class + add_title + add_params' . ($addPassOnParams ? '+"' . $addPassOnParams . '"' : '') . '+(anchor?anchor:"");
				window.location.href = theLocation;
				return false;
			}
		';
        /**
         * Splits parts of $this->bparams
         *
         * @see $bparams
         */
        $pArr = explode('|', $this->bparams);
        // This is JavaScript especially for the TBE Element Browser!
        $formFieldName = 'data[' . $pArr[0] . '][' . $pArr[1] . '][' . $pArr[2] . ']';
        // insertElement - Call check function (e.g. for uniqueness handling):
        if ($pArr[4] && $pArr[5]) {
            $JScodeCheck = '
					// Call a check function in the opener window (e.g. for uniqueness handling):
				if (parent.window.opener) {
					var res = parent.window.opener.' . $pArr[5] . '("' . addslashes($pArr[4]) . '",table,uid,type);
					if (!res.passed) {
						if (res.message) alert(res.message);
						performAction = false;
					}
				} else {
					alert("Error - reference to main window is not set properly!");
					parent.close();
				}
			';
        }
        // insertElement - Call helper function:
        if ($pArr[4] && $pArr[6]) {
            $JScodeHelper = '
						// Call helper function to manage data in the opener window:
					if (parent.window.opener) {
						parent.window.opener.' . $pArr[6] . '("' . addslashes($pArr[4]) . '",table,uid,type,"' . addslashes($pArr[0]) . '");
					} else {
						alert("Error - reference to main window is not set properly!");
						parent.close();
					}
			';
        }
        // insertElement - perform action commands:
        if ($pArr[4] && $pArr[7]) {
            // Call user defined action function:
            $JScodeAction = '
					if (parent.window.opener) {
						parent.window.opener.' . $pArr[7] . '("' . addslashes($pArr[4]) . '",table,uid,type);
						if (close) { focusOpenerAndClose(close); }
					} else {
						alert("Error - reference to main window is not set properly!");
						if (close) { parent.close(); }
					}
			';
            $JScodeActionMultiple = '
						// Call helper function to manage data in the opener window:
					if (parent.window.opener) {
						parent.window.opener.' . $pArr[7] . 'Multiple("' . addslashes($pArr[4]) . '",table,uid,type,"' . addslashes($pArr[0]) . '");
					} else {
						alert("Error - reference to main window is not set properly!");
						parent.close();
					}
			';
        } elseif ($pArr[0] && !$pArr[1] && !$pArr[2]) {
            $JScodeAction = '
					addElement(filename,table+"_"+uid,fp,close);
			';
        } else {
            $JScodeAction = '
					if (setReferences()) {
						parent.window.opener.group_change("add","' . $pArr[0] . '","' . $pArr[1] . '","' . $pArr[2] . '",elRef,targetDoc);
					} else {
						alert("Error - reference to main window is not set properly!");
					}
					focusOpenerAndClose(close);
			';
        }
        $JScode .= '
			var elRef="";
			var targetDoc="";

			function launchView(url) {	//
				var thePreviewWindow="";
				thePreviewWindow = window.open("' . $GLOBALS['BACK_PATH'] . 'show_item.php?table="+url,"ShowItem","height=300,width=410,status=0,menubar=0,resizable=0,location=0,directories=0,scrollbars=1,toolbar=0");
				if (thePreviewWindow && thePreviewWindow.focus) {
					thePreviewWindow.focus();
				}
			}
			function setReferences() {	//
				if (parent.window.opener && parent.window.opener.content && parent.window.opener.content.document.editform && parent.window.opener.content.document.editform["' . $formFieldName . '"]) {
					targetDoc = parent.window.opener.content.document;
					elRef = targetDoc.editform["' . $formFieldName . '"];
					return true;
				} else {
					return false;
				}
			}
			function insertElement(table, uid, type, filename, fp, filetype, imagefile, action, close) {	//
				var performAction = true;
				' . $JScodeCheck . '
					// Call performing function and finish this action:
				if (performAction) {
						' . $JScodeHelper . $JScodeAction . '
				}
				return false;
			}
			function insertMultiple(table, uid) {
				var type = "";
						' . $JScodeActionMultiple . '
				return false;
			}
			function addElement(elName, elValue, altElValue, close) {	//
				if (parent.window.opener && parent.window.opener.setFormValueFromBrowseWin) {
					parent.window.opener.setFormValueFromBrowseWin("' . $pArr[0] . '",altElValue?altElValue:elValue,elName);
					focusOpenerAndClose(close);
				} else {
					alert("Error - reference to main window is not set properly!");
					parent.close();
				}
			}
			function focusOpenerAndClose(close) {	//
				BrowseLinks.focusOpenerAndClose(close);
			}
		';
        // extends JavaScript code
        if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode'])) {
            $_params = array('conf' => &$conf, 'wizardUpdate' => $update, 'addPassOnParams' => $addPassOnParams);
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/class.browse_links.php']['extendJScode'] as $objRef) {
                $processor =& \TYPO3\CMS\Core\Utility\GeneralUtility::getUserObj($objRef);
                $JScode .= $processor->extendJScode($_params, $this);
            }
        }
        // Finally, add the accumulated JavaScript to the template object:
        $this->doc->JScode .= $this->doc->wrapScriptTags($JScode);
    }
 /**
  * @param ServerRequestInterface $request
  */
 protected function initVariables(ServerRequestInterface $request)
 {
     parent::initVariables($request);
     $queryParameters = $request->getQueryParams();
     $this->bparams = isset($queryParameters['bparams']) ? $queryParameters['bparams'] : '';
     $this->siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
     $currentLinkParts = isset($queryParameters['curUrl']) ? $queryParameters['curUrl'] : [];
     if (isset($currentLinkParts['all'])) {
         $currentLinkParts = GeneralUtility::get_tag_attributes($queryParameters['curUrl']['all']);
         $currentLinkParts['url'] = htmlspecialchars_decode($currentLinkParts['href']);
         unset($currentLinkParts['href']);
     }
     $this->currentLinkParts = $currentLinkParts;
     // Process bparams
     $pArr = explode('|', $this->bparams);
     $pRteArr = explode(':', $pArr[1]);
     $this->editorNo = $pRteArr[0];
     $this->contentTypo3Language = $pRteArr[1];
     $this->RTEtsConfigParams = $pArr[2];
     if (!$this->editorNo) {
         $this->editorNo = GeneralUtility::_GP('editorNo');
         $this->contentTypo3Language = GeneralUtility::_GP('contentTypo3Language');
         $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
     }
     $pArr[1] = implode(':', array($this->editorNo, $this->contentTypo3Language));
     $pArr[2] = $this->RTEtsConfigParams;
     $this->bparams = implode('|', $pArr);
     $this->contentLanguageService->init($this->contentTypo3Language);
     $this->buttonConfig = isset($this->RTEProperties['default.']['buttons.']['link.']) ? $this->RTEProperties['default.']['buttons.']['link.'] : [];
     $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
     $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
     $this->thisConfig = BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
 }
Пример #14
0
 /**
  * @param ServerRequestInterface $request
  */
 protected function initVariables(ServerRequestInterface $request)
 {
     parent::initVariables($request);
     $queryParameters = $request->getQueryParams();
     $this->siteUrl = GeneralUtility::getIndpEnv('TYPO3_SITE_URL');
     $currentLinkParts = isset($queryParameters['curUrl']) ? $queryParameters['curUrl'] : [];
     $this->currentLinkParts = $currentLinkParts;
     $this->editorId = GeneralUtility::_GP('editorId');
     $this->contentsLanguage = GeneralUtility::_GP('contentsLanguage');
     $this->RTEtsConfigParams = GeneralUtility::_GP('RTEtsConfigParams');
     $this->contentLanguageService->init($this->contentsLanguage);
     $RTEtsConfigParts = explode(':', $this->RTEtsConfigParams);
     $RTEsetup = $this->getBackendUser()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
     $this->RTEProperties = $RTEsetup['properties'];
     $this->thisConfig = BackendUtility::RTEsetup($this->RTEProperties, $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
     $this->buttonConfig = $this->thisConfig['buttons.']['link.'] ?? [];
 }
Пример #15
0
    /**
     * Rich Text Editor (RTE) user element selector
     *
     * @param 	[type]		$openKeys: ...
     * @return 	[type]		...
     * @todo Define visibility
     */
    public function main_user($openKeys)
    {
        // Starting content:
        $content = $this->doc->startPage($GLOBALS['LANG']->getLL('Insert Custom Element', 1));
        $RTEtsConfigParts = explode(':', \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('RTEtsConfigParams'));
        $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
        $thisConfig = \TYPO3\CMS\Backend\Utility\BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
        if (is_array($thisConfig['userElements.'])) {
            $categories = array();
            foreach ($thisConfig['userElements.'] as $k => $value) {
                $ki = intval($k);
                $v = $thisConfig['userElements.'][$ki . '.'];
                if (substr($k, -1) == '.' && is_array($v)) {
                    $subcats = array();
                    $openK = $ki;
                    if ($openKeys[$openK]) {
                        $mArray = '';
                        switch ((string) $v['load']) {
                            case 'images_from_folder':
                                $mArray = array();
                                if ($v['path'] && @is_dir(PATH_site . $v['path'])) {
                                    $files = \TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir(PATH_site . $v['path'], 'gif,jpg,jpeg,png', 0, '');
                                    if (is_array($files)) {
                                        $c = 0;
                                        foreach ($files as $filename) {
                                            $iInfo = @getimagesize(PATH_site . $v['path'] . $filename);
                                            $iInfo = $this->calcWH($iInfo, 50, 100);
                                            $ks = (string) (100 + $c);
                                            $mArray[$ks] = $filename;
                                            $mArray[$ks . '.'] = array('content' => '<img src="' . $this->siteUrl . $v['path'] . $filename . '" />', '_icon' => '<img src="' . $this->siteUrl . $v['path'] . $filename . '" ' . $iInfo[3] . ' />', 'description' => $GLOBALS['LANG']->getLL('filesize') . ': ' . str_replace('&nbsp;', ' ', \TYPO3\CMS\Core\Utility\GeneralUtility::formatSize(@filesize(PATH_site . $v['path'] . $filename))) . ', ' . $GLOBALS['LANG']->getLL('pixels', 1) . ': ' . $iInfo[0] . 'x' . $iInfo[1]);
                                            $c++;
                                        }
                                    }
                                }
                                break;
                        }
                        if (is_array($mArray)) {
                            if ($v['merge']) {
                                $v = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule($mArray, $v);
                            } else {
                                $v = $mArray;
                            }
                        }
                        foreach ($v as $k2 => $dummyValue) {
                            $k2i = intval($k2);
                            if (substr($k2, -1) == '.' && is_array($v[$k2i . '.'])) {
                                $title = trim($v[$k2i]);
                                if (!$title) {
                                    $title = '[' . $GLOBALS['LANG']->getLL('noTitle', 1) . ']';
                                } else {
                                    $title = $GLOBALS['LANG']->sL($title, 1);
                                }
                                $description = $GLOBALS['LANG']->sL($v[$k2i . '.']['description'], 1) . '<br />';
                                if (!$v[$k2i . '.']['dontInsertSiteUrl']) {
                                    $v[$k2i . '.']['content'] = str_replace('###_URL###', $this->siteUrl, $v[$k2i . '.']['content']);
                                }
                                $logo = $v[$k2i . '.']['_icon'] ? $v[$k2i . '.']['_icon'] : '';
                                $onClickEvent = '';
                                switch ((string) $v[$k2i . '.']['mode']) {
                                    case 'wrap':
                                        $wrap = explode('|', $v[$k2i . '.']['content']);
                                        $onClickEvent = 'wrapHTML(' . $GLOBALS['LANG']->JScharCode($wrap[0]) . ',' . $GLOBALS['LANG']->JScharCode($wrap[1]) . ',false);';
                                        break;
                                    case 'processor':
                                        $script = trim($v[$k2i . '.']['submitToScript']);
                                        if (substr($script, 0, 4) != 'http') {
                                            $script = $this->siteUrl . $script;
                                        }
                                        if ($script) {
                                            $onClickEvent = 'processSelection(' . $GLOBALS['LANG']->JScharCode($script) . ');';
                                        }
                                        break;
                                    case 'insert':
                                    default:
                                        $onClickEvent = 'insertHTML(' . $GLOBALS['LANG']->JScharCode($v[$k2i . '.']['content']) . ');';
                                        break;
                                }
                                $A = array('<a href="#" onClick="' . $onClickEvent . 'return false;">', '</a>');
                                $subcats[$k2i] = '<tr>
									<td><img src="clear.gif" width="18" height="1" /></td>
									<td class="bgColor4" valign="top">' . $A[0] . $logo . $A[1] . '</td>
									<td class="bgColor4" valign="top">' . $A[0] . '<strong>' . $title . '</strong><br />' . $description . $A[1] . '</td>
								</tr>';
                            }
                        }
                        ksort($subcats);
                    }
                    $categories[$ki] = implode('', $subcats);
                }
            }
            ksort($categories);
            // Render menu of the items:
            $lines = array();
            foreach ($categories as $k => $v) {
                $title = trim($thisConfig['userElements.'][$k]);
                $openK = $k;
                if (!$title) {
                    $title = '[' . $GLOBALS['LANG']->getLL('noTitle', 1) . ']';
                } else {
                    $title = $GLOBALS['LANG']->sL($title, 1);
                }
                $lines[] = '<tr><td colspan="3" class="bgColor5"><a href="#" title="' . $GLOBALS['LANG']->getLL('expand', 1) . '" onClick="jumpToUrl(\'?OC_key=' . ($openKeys[$openK] ? 'C|' : 'O|') . $openK . '\');return false;"><img' . \TYPO3\CMS\Backend\Utility\IconUtility::skinImg($GLOBALS['BACK_PATH'], 'gfx/ol/' . ($openKeys[$openK] ? 'minus' : 'plus') . 'bullet.gif', 'width="18" height="16"') . ' title="' . $GLOBALS['LANG']->getLL('expand', 1) . '" /><strong>' . $title . '</strong></a></td></tr>';
                $lines[] = $v;
            }
            $content .= '<table border="0" cellpadding="1" cellspacing="1">' . implode('', $lines) . '</table>';
        }
        $content .= $this->doc->endPage();
        return $content;
    }
Пример #16
0
 /**
  * This will render a <textarea> OR RTE area form field,
  * possibly with various control/validation features
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->data['tableName'];
     $fieldName = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $backendUser = $this->getBackendUserAuthentication();
     $this->resultArray = $this->initializeResultArray();
     $this->defaultExtras = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     $this->pidOfPageRecord = $table === 'pages' && MathUtility::canBeInterpretedAsInteger($row['uid']) ? (int) $row['uid'] : (int) $row['pid'];
     BackendUtility::fixVersioningPid($table, $row);
     $this->pidOfVersionedMotherRecord = (int) $row['pid'];
     $this->vanillaRteTsConfig = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($this->pidOfPageRecord));
     $this->processedRteConfiguration = BackendUtility::RTEsetup($this->vanillaRteTsConfig['properties'], $table, $fieldName, $this->data['recordTypeValue']);
     $this->client = $this->clientInfo();
     $this->domIdentifier = preg_replace('/[^a-zA-Z0-9_:.-]/', '_', $parameterArray['itemFormElName']);
     $this->domIdentifier = htmlspecialchars(preg_replace('/^[^a-zA-Z]/', 'x', $this->domIdentifier));
     $this->initializeLanguageRelatedProperties();
     // Get skin file name from Page TSConfig if any
     $skinFilename = trim($this->processedRteConfiguration['skin']) ?: 'EXT:rtehtmlarea/Resources/Public/Css/Skin/htmlarea.css';
     $skinFilename = $this->getFullFileName($skinFilename);
     $skinDirectory = dirname($skinFilename);
     // jQuery UI Resizable style sheet and main skin stylesheet
     $this->resultArray['stylesheetFiles'][] = $skinDirectory . '/jquery-ui-resizable.css';
     $this->resultArray['stylesheetFiles'][] = $skinFilename;
     $this->enableRegisteredPlugins();
     // Configure toolbar
     $this->setToolbar();
     // Check if some plugins need to be disabled
     $this->setPlugins();
     // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
     $this->pluginEnabledCumulativeArray = $this->pluginEnabledArray;
     $this->addInstanceJavaScriptRegistration();
     $this->addOnSubmitJavaScriptCode();
     // Add RTE JavaScript
     $this->loadRequireModulesForRTE();
     // Create language labels
     $this->createJavaScriptLanguageLabelsFromFiles();
     // Get RTE init JS code
     $this->resultArray['additionalJavaScriptPost'][] = $this->getRteInitJsCode();
     $html = $this->getMainHtml();
     $this->resultArray['html'] = $this->renderWizards(array($html), $parameterArray['fieldConf']['config']['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $this->defaultExtras, true);
     return $this->resultArray;
 }
Пример #17
0
    /**
     * Generation of TCEform elements of the type "text"
     * This will render a <textarea> OR RTE area form field, possibly with various control/validation features
     *
     * @param string $table The table name of the record
     * @param string $field The field name which this element is supposed to edit
     * @param array $row The record data array where the value(s) for the field can be found
     * @param array $PA An array with additional configuration options.
     * @return string The HTML code for the TCEform field
     * @todo Define visibility
     */
    public function getSingleField_typeText($table, $field, $row, &$PA)
    {
        // Init config:
        $config = $PA['fieldConf']['config'];
        $evalList = GeneralUtility::trimExplode(',', $config['eval'], TRUE);
        if ($this->renderReadonly || $config['readOnly']) {
            return $this->getSingleField_typeNone_render($config, $PA['itemFormElValue']);
        }
        // Setting columns number:
        $cols = MathUtility::forceIntegerInRange($config['cols'] ? $config['cols'] : 30, 5, $this->maxTextareaWidth);
        // Setting number of rows:
        $origRows = $rows = MathUtility::forceIntegerInRange($config['rows'] ? $config['rows'] : 5, 1, 20);
        if (strlen($PA['itemFormElValue']) > $this->charsPerRow * 2) {
            $cols = $this->maxTextareaWidth;
            $rows = MathUtility::forceIntegerInRange(round(strlen($PA['itemFormElValue']) / $this->charsPerRow), count(explode(LF, $PA['itemFormElValue'])), 20);
            if ($rows < $origRows) {
                $rows = $origRows;
            }
        }
        if (in_array('required', $evalList)) {
            $this->requiredFields[$table . '_' . $row['uid'] . '_' . $field] = $PA['itemFormElName'];
        }
        // Init RTE vars:
        // Set TRUE, if the RTE is loaded; If not a normal textarea is shown.
        $RTEwasLoaded = 0;
        // Set TRUE, if the RTE would have been loaded if it wasn't for the disable-RTE flag in the bottom of the page...
        $RTEwouldHaveBeenLoaded = 0;
        // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
        $specConf = $this->getSpecConfFromString($PA['extra'], $PA['fieldConf']['defaultExtras']);
        // Setting up the altItem form field, which is a hidden field containing the value
        $altItem = '<input type="hidden" name="' . htmlspecialchars($PA['itemFormElName']) . '" value="' . htmlspecialchars($PA['itemFormElValue']) . '" />';
        $item = '';
        // If RTE is generally enabled (TYPO3_CONF_VARS and user settings)
        if ($this->RTEenabled) {
            $p = BackendUtility::getSpecConfParametersFromArray($specConf['rte_transform']['parameters']);
            // If the field is configured for RTE and if any flag-field is not set to disable it.
            if (isset($specConf['richtext']) && (!$p['flag'] || !$row[$p['flag']])) {
                BackendUtility::fixVersioningPid($table, $row);
                list($tscPID, $thePidValue) = $this->getTSCpid($table, $row['uid'], $row['pid']);
                // If the pid-value is not negative (that is, a pid could NOT be fetched)
                if ($thePidValue >= 0) {
                    $RTEsetup = $this->getBackendUserAuthentication()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($tscPID));
                    $RTEtypeVal = BackendUtility::getTCAtypeValue($table, $row);
                    $thisConfig = BackendUtility::RTEsetup($RTEsetup['properties'], $table, $field, $RTEtypeVal);
                    if (!$thisConfig['disabled']) {
                        if (!$this->disableRTE) {
                            $this->RTEcounter++;
                            // Find alternative relative path for RTE images/links:
                            $eFile = RteHtmlParser::evalWriteFile($specConf['static_write'], $row);
                            $RTErelPath = is_array($eFile) ? dirname($eFile['relEditFile']) : '';
                            // Get RTE object, draw form and set flag:
                            $RTEobj = BackendUtility::RTEgetObj();
                            $item = $RTEobj->drawRTE($this, $table, $field, $row, $PA, $specConf, $thisConfig, $RTEtypeVal, $RTErelPath, $thePidValue);
                            // Wizard:
                            $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, 1);
                            $RTEwasLoaded = 1;
                        } else {
                            $RTEwouldHaveBeenLoaded = 1;
                            $this->commentMessages[] = $PA['itemFormElName'] . ': RTE is disabled by the on-page RTE-flag (probably you can enable it by the check-box in the bottom of this page!)';
                        }
                    } else {
                        $this->commentMessages[] = $PA['itemFormElName'] . ': RTE is disabled by the Page TSconfig, "RTE"-key (eg. by RTE.default.disabled=0 or such)';
                    }
                } else {
                    $this->commentMessages[] = $PA['itemFormElName'] . ': PID value could NOT be fetched. Rare error, normally with new records.';
                }
            } else {
                if (!isset($specConf['richtext'])) {
                    $this->commentMessages[] = $PA['itemFormElName'] . ': RTE was not configured for this field in TCA-types';
                }
                if (!(!$p['flag'] || !$row[$p['flag']])) {
                    $this->commentMessages[] = $PA['itemFormElName'] . ': Field-flag (' . $PA['flag'] . ') has been set to disable RTE!';
                }
            }
        }
        // Display ordinary field if RTE was not loaded.
        if (!$RTEwasLoaded) {
            // Show message, if no RTE (field can only be edited with RTE!)
            if ($specConf['rte_only']) {
                $item = '<p><em>' . htmlspecialchars($this->getLL('l_noRTEfound')) . '</em></p>';
            } else {
                if ($specConf['nowrap']) {
                    $wrap = 'off';
                } else {
                    $wrap = $config['wrap'] ?: 'virtual';
                }
                $classes = array();
                if ($specConf['fixed-font']) {
                    $classes[] = 'fixed-font';
                }
                if ($specConf['enable-tab']) {
                    $classes[] = 'enable-tab';
                }
                $formWidthText = $this->formWidthText($cols, $wrap);
                // Extract class attributes from $formWidthText (otherwise it would be added twice to the output)
                $res = array();
                if (preg_match('/ class="(.+?)"/', $formWidthText, $res)) {
                    $formWidthText = str_replace(' class="' . $res[1] . '"', '', $formWidthText);
                    $classes = array_merge($classes, explode(' ', $res[1]));
                }
                if (count($classes)) {
                    $class = ' class="tceforms-textarea ' . implode(' ', $classes) . '"';
                } else {
                    $class = 'tceforms-textarea';
                }
                $evalList = GeneralUtility::trimExplode(',', $config['eval'], TRUE);
                foreach ($evalList as $func) {
                    switch ($func) {
                        case 'required':
                            $this->registerRequiredProperty('field', $table . '_' . $row['uid'] . '_' . $field, $PA['itemFormElName']);
                            break;
                        default:
                            // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
                            // and \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_text_Eval()
                            $evalObj = GeneralUtility::getUserObj($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func] . ':&' . $func);
                            if (is_object($evalObj) && method_exists($evalObj, 'deevaluateFieldValue')) {
                                $_params = array('value' => $PA['itemFormElValue']);
                                $PA['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
                            }
                    }
                }
                $iOnChange = implode('', $PA['fieldChangeFunc']);
                $item .= '
							<textarea ' . 'id="' . uniqid('tceforms-textarea-') . '" ' . 'name="' . $PA['itemFormElName'] . '"' . $formWidthText . $class . ' ' . 'rows="' . $rows . '" ' . 'wrap="' . $wrap . '" ' . 'onchange="' . htmlspecialchars($iOnChange) . '"' . $this->getPlaceholderAttribute($table, $field, $config, $row) . $PA['onFocus'] . '>' . GeneralUtility::formatForTextarea($PA['itemFormElValue']) . '</textarea>';
                $item = $this->renderWizards(array($item, $altItem), $config['wizards'], $table, $row, $field, $PA, $PA['itemFormElName'], $specConf, $RTEwouldHaveBeenLoaded);
            }
        }
        // Return field HTML:
        return $item;
    }
Пример #18
0
 /**
  * checks if
  * $this->pObj->thisConfig['tx_linkhandler.'] is set, and if not it trys to load default from
  * TSConfig key mod.tx_linkhandler.
  * (in case the hook is called from a RTE, this configuration might exist because it is configured in RTE.defaul.tx_linkhandler)
  * In mode RTE: the parameter RTEtsConfigParams have to exist
  * In mode WIzard: the parameter P[pid] have to exist
  *
  * @return void
  */
 private function _checkConfigAndGetDefault()
 {
     if ($this->pObj->mode == 'rte') {
         $RTEtsConfigParts = explode(':', $this->pObj->RTEtsConfigParams);
         $RTEsetup = $GLOBALS["BE_USER"]->getTSConfig('RTE', \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
         $this->pObj->thisConfig = \TYPO3\CMS\Backend\Utility\BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
     } elseif (!is_array($this->pObj->thisConfig['tx_linkhandler.'])) {
         $pid = $this->getCurrentPageId();
         $modTSconfig = $GLOBALS["BE_USER"]->getTSConfig("mod.tx_linkhandler", \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($pid));
         $this->pObj->thisConfig['tx_linkhandler.'] = $modTSconfig['properties'];
     }
 }
Пример #19
0
    /**
     * Rich Text Editor (RTE) user element selector
     *
     * @param array $openKeys
     * @return string
     */
    public function main_user($openKeys)
    {
        // Starting content:
        $content = $this->doc->startPage(htmlspecialchars($GLOBALS['LANG']->getLL('Insert Custom Element')));
        $RTEtsConfigParts = explode(':', \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('RTEtsConfigParams'));
        $RTEsetup = $GLOBALS['BE_USER']->getTSConfig('RTE', \TYPO3\CMS\Backend\Utility\BackendUtility::getPagesTSconfig($RTEtsConfigParts[5]));
        $thisConfig = \TYPO3\CMS\Backend\Utility\BackendUtility::RTEsetup($RTEsetup['properties'], $RTEtsConfigParts[0], $RTEtsConfigParts[2], $RTEtsConfigParts[4]);
        if (is_array($thisConfig['userElements.'])) {
            $categories = [];
            foreach ($thisConfig['userElements.'] as $k => $value) {
                $ki = (int) $k;
                $v = $thisConfig['userElements.'][$ki . '.'];
                if (substr($k, -1) == '.' && is_array($v)) {
                    $subcats = [];
                    $openK = $ki;
                    if ($openKeys[$openK]) {
                        $mArray = '';
                        if ($v['load'] === 'images_from_folder') {
                            $mArray = [];
                            if ($v['path'] && @is_dir(PATH_site . $v['path'])) {
                                $files = \TYPO3\CMS\Core\Utility\GeneralUtility::getFilesInDir(PATH_site . $v['path'], 'gif,jpg,jpeg,png', 0, '');
                                if (is_array($files)) {
                                    $c = 0;
                                    foreach ($files as $filename) {
                                        $iInfo = @getimagesize(PATH_site . $v['path'] . $filename);
                                        $iInfo = $this->calcWH($iInfo, 50, 100);
                                        $ks = (string) (100 + $c);
                                        $mArray[$ks] = $filename;
                                        $mArray[$ks . '.'] = ['content' => '<img src="' . $this->siteUrl . $v['path'] . $filename . '" />', '_icon' => '<img src="' . $this->siteUrl . $v['path'] . $filename . '" ' . $iInfo[3] . ' />', 'description' => $GLOBALS['LANG']->getLL('filesize') . ': ' . str_replace('&nbsp;', ' ', \TYPO3\CMS\Core\Utility\GeneralUtility::formatSize(@filesize(PATH_site . $v['path'] . $filename))) . ', ' . htmlspecialchars($GLOBALS['LANG']->getLL('pixels')) . ': ' . $iInfo[0] . 'x' . $iInfo[1]];
                                        $c++;
                                    }
                                }
                            }
                        }
                        if (is_array($mArray)) {
                            if ($v['merge']) {
                                \TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($mArray, $v);
                                $v = $mArray;
                            } else {
                                $v = $mArray;
                            }
                        }
                        foreach ($v as $k2 => $dummyValue) {
                            $k2i = (int) $k2;
                            if (substr($k2, -1) == '.' && is_array($v[$k2i . '.'])) {
                                $title = trim($v[$k2i]);
                                if (!$title) {
                                    $title = '[' . htmlspecialchars($GLOBALS['LANG']->getLL('noTitle')) . ']';
                                } else {
                                    $title = htmlspecialchars($GLOBALS['LANG']->sL($title));
                                }
                                $description = htmlspecialchars($GLOBALS['LANG']->sL($v[$k2i . '.']['description'])) . '<br />';
                                if (!$v[$k2i . '.']['dontInsertSiteUrl']) {
                                    $v[$k2i . '.']['content'] = str_replace('###_URL###', $this->siteUrl, $v[$k2i . '.']['content']);
                                }
                                $logo = $v[$k2i . '.']['_icon'] ?: '';
                                $onClickEvent = '';
                                switch ((string) $v[$k2i . '.']['mode']) {
                                    case 'wrap':
                                        $wrap = explode('|', $v[$k2i . '.']['content']);
                                        $onClickEvent = 'wrapHTML(' . GeneralUtility::quoteJSvalue($wrap[0]) . ',' . GeneralUtility::quoteJSvalue($wrap[1]) . ',false);';
                                        break;
                                    case 'processor':
                                        $script = trim($v[$k2i . '.']['submitToScript']);
                                        if (substr($script, 0, 4) != 'http') {
                                            $script = $this->siteUrl . $script;
                                        }
                                        if ($script) {
                                            $onClickEvent = 'processSelection(' . GeneralUtility::quoteJSvalue($script) . ');';
                                        }
                                        break;
                                    case 'insert':
                                    default:
                                        $onClickEvent = 'insertHTML(' . GeneralUtility::quoteJSvalue($v[$k2i . '.']['content']) . ');';
                                }
                                $A = ['<a href="#" onClick="' . $onClickEvent . 'return false;">', '</a>'];
                                $subcats[$k2i] = '<tr>
									<td></td>
									<td>' . $A[0] . $logo . $A[1] . '</td>
									<td>' . $A[0] . '<strong>' . $title . '</strong><br />' . $description . $A[1] . '</td>
								</tr>';
                            }
                        }
                        ksort($subcats);
                    }
                    $categories[$ki] = implode('', $subcats);
                }
            }
            ksort($categories);
            // Render menu of the items:
            $lines = [];
            foreach ($categories as $k => $v) {
                $title = trim($thisConfig['userElements.'][$k]);
                $openK = $k;
                if (!$title) {
                    $title = '[' . htmlspecialchars($GLOBALS['LANG']->getLL('noTitle')) . ']';
                } else {
                    $title = htmlspecialchars($GLOBALS['LANG']->sL($title));
                }
                $uriBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Routing\UriBuilder::class);
                $url = (string) $uriBuilder->buildUriFromRoute('rtehtmlarea_wizard_user_elements', ['OC_key' => ($openKeys[$openK] ? 'C|' : 'O|') . $openK]);
                $lines[] = '<tr><td colspan="3"><a href="#" title="' . htmlspecialchars($GLOBALS['LANG']->getLL('expand')) . '" onClick="jumpToUrl(' . GeneralUtility::quoteJSvalue($url) . ');return false;"><i class="fa fa-caret-square-o-' . ($openKeys[$openK] ? 'left' : 'right') . '" title="' . htmlspecialchars($GLOBALS['LANG']->getLL('expand')) . '"></i><strong>' . $title . '</strong></a></td></tr>';
                $lines[] = $v;
            }
            $content .= '<table class="table table-striped table-hover">' . implode('', $lines) . '</table>';
        }
        $content .= $this->doc->endPage();
        return $content;
    }