1<?php 2namespace TYPO3\CMS\Fluid\ViewHelpers\Format; 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 17use TYPO3\CMS\Core\Utility\GeneralUtility; 18use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; 19use TYPO3\CMS\Extbase\Object\ObjectManager; 20use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; 21use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface; 22use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper; 23use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic; 24 25/** 26 * Renders a string by passing it to a TYPO3 `parseFunc`_. 27 * You can either specify a path to the TypoScript setting or set the `parseFunc`_ options directly. 28 * By default :ts:`lib.parseFunc_RTE` is used to parse the string. 29 * 30 * Examples 31 * ======== 32 * 33 * Default parameters 34 * ------------------ 35 * 36 * :: 37 * 38 * <f:format.html>foo <b>bar</b>. Some <LINK 1>link</LINK>.</f:format.html> 39 * 40 * Output:: 41 * 42 * <p class="bodytext">foo <b>bar</b>. Some <a href="index.php?id=1" >link</a>.</p> 43 * 44 * Depending on TYPO3 setup. 45 * 46 * Custom parseFunc 47 * ---------------- 48 * 49 * :: 50 * 51 * <f:format.html parseFuncTSPath="lib.parseFunc">foo <b>bar</b>. Some <LINK 1>link</LINK>.</f:format.html> 52 * 53 * Output:: 54 * 55 * foo <b>bar</b>. Some <a href="index.php?id=1" >link</a>. 56 * 57 * Inline notation 58 * --------------- 59 * 60 * :: 61 * 62 * {someText -> f:format.html(parseFuncTSPath: 'lib.parseFunc')} 63 * 64 * Output:: 65 * 66 * foo <b>bar</b>. Some <a href="index.php?id=1" >link</a>. 67 * 68 * .. _parseFunc: https://docs.typo3.org/m/typo3/reference-typoscript/master/en-us/Functions/Parsefunc.html 69 */ 70class HtmlViewHelper extends AbstractViewHelper 71{ 72 use CompileWithRenderStatic; 73 74 /** 75 * @var \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController contains a backup of the current $GLOBALS['TSFE'] if used in BE mode 76 */ 77 protected static $tsfeBackup; 78 79 /** 80 * Children must not be escaped, to be able to pass {bodytext} directly to it 81 * 82 * @var bool 83 */ 84 protected $escapeChildren = false; 85 86 /** 87 * Plain HTML should be returned, no output escaping allowed 88 * 89 * @var bool 90 */ 91 protected $escapeOutput = false; 92 93 /** 94 * Initialize arguments. 95 * 96 * @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception 97 */ 98 public function initializeArguments() 99 { 100 $this->registerArgument('parseFuncTSPath', 'string', 'Path to TypoScript parseFunc setup', false, 'lib.parseFunc_RTE'); 101 } 102 103 /** 104 * @param array $arguments 105 * @param \Closure $renderChildrenClosure 106 * @param RenderingContextInterface $renderingContext 107 * 108 * @return string the parsed string. 109 */ 110 public static function renderStatic(array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext) 111 { 112 $parseFuncTSPath = $arguments['parseFuncTSPath']; 113 if (TYPO3_MODE === 'BE') { 114 self::simulateFrontendEnvironment(); 115 } 116 $value = $renderChildrenClosure(); 117 $contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class); 118 $contentObject->start([]); 119 $content = $contentObject->parseFunc($value, [], '< ' . $parseFuncTSPath); 120 if (TYPO3_MODE === 'BE') { 121 self::resetFrontendEnvironment(); 122 } 123 return $content; 124 } 125 126 /** 127 * Copies the specified parseFunc configuration to $GLOBALS['TSFE']->tmpl->setup in Backend mode 128 * This somewhat hacky work around is currently needed because the parseFunc() function of \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer relies on those variables to be set 129 */ 130 protected static function simulateFrontendEnvironment() 131 { 132 self::$tsfeBackup = $GLOBALS['TSFE'] ?? null; 133 $GLOBALS['TSFE'] = new \stdClass(); 134 $GLOBALS['TSFE']->tmpl = new \stdClass(); 135 $objectManager = GeneralUtility::makeInstance(ObjectManager::class); 136 $configurationManager = $objectManager->get(ConfigurationManagerInterface::class); 137 $GLOBALS['TSFE']->tmpl->setup = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT); 138 } 139 140 /** 141 * Resets $GLOBALS['TSFE'] if it was previously changed by simulateFrontendEnvironment() 142 * 143 * @see simulateFrontendEnvironment() 144 */ 145 protected static function resetFrontendEnvironment() 146 { 147 $GLOBALS['TSFE'] = self::$tsfeBackup; 148 } 149} 150