Files

110 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace TYPO3\CMS\Fluid\ViewHelpers\Format;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Core\Http\ApplicationType;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Reflection\ObjectAccess;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
/**
* ViewHelper to render a string which can contain HTML markup
* by passing it to a TYPO3 `parseFunc`. This can sanitize
* unwanted HTML tags and attributes, and keep wanted HTML syntax and
* take care of link substitution and other parsing.
* Either specify a path to the TypoScript setting or set the `parseFunc` options directly.
* By default, `lib.parseFunc_RTE` is used to parse the string.
*
* ```
* <f:format.html parseFuncTSPath="lib.myCustomParseFunc">
* {$project} is a cool <b>CMS</b> (<a href="https://www.typo3.org">TYPO3</a>).
* </f:format.html>
* ```
*
* **Note:** The ViewHelper must not be used in backend context, as it triggers frontend logic.
* Instead, use `<f:sanitize.html>` within backend context to secure a given HTML string
* or `<f:transform.html>` to parse links in HTML.
*
* @see https://docs.typo3.org/permalink/t3viewhelper:typo3-fluid-format-html
* @see https://docs.typo3.org/permalink/t3tsref:parsefunc
*/
final class HtmlViewHelper extends AbstractViewHelper
{
/**
* Children must not be escaped, to be able to pass {bodytext} directly to it
*
* @var bool
*/
protected $escapeChildren = false;
/**
* Plain HTML should be returned, no output escaping allowed
*
* @var bool
*/
protected $escapeOutput = false;
public function initializeArguments(): void
{
$this->registerArgument('parseFuncTSPath', 'string', 'Path to the TypoScript parseFunc setup.', false, 'lib.parseFunc_RTE');
$this->registerArgument('data', 'mixed', 'Initialize the content object with this set of data. Either an array or object.');
$this->registerArgument('current', 'string', 'Initialize the content object with this value for current property.');
$this->registerArgument('currentValueKey', 'string', 'Define the value key, used to locate the current value for the content object');
$this->registerArgument('table', 'string', 'The table name associated with the "data" argument.', false, '');
}
public function render(): string
{
$parseFuncTSPath = $this->arguments['parseFuncTSPath'];
$data = $this->arguments['data'];
$current = $this->arguments['current'];
$currentValueKey = $this->arguments['currentValueKey'];
$table = $this->arguments['table'];
$request = null;
if ($this->renderingContext->hasAttribute(ServerRequestInterface::class)) {
$request = $this->renderingContext->getAttribute(ServerRequestInterface::class);
}
$isBackendRequest = $request instanceof ServerRequestInterface && ApplicationType::fromRequest($request)->isBackend();
if ($isBackendRequest) {
throw new \RuntimeException(
'Using f:format.html in backend context is not allowed. Use f:sanitize.html or f:transform.html instead.',
1686813703
);
}
$value = $this->renderChildren() ?? '';
// Prepare data array
if (is_object($data)) {
$data = ObjectAccess::getGettableProperties($data);
} elseif (!is_array($data)) {
$data = (array)$data;
}
$contentObject = GeneralUtility::makeInstance(ContentObjectRenderer::class);
$contentObject->setRequest($request);
$contentObject->start($data, $table);
if ($current !== null) {
$contentObject->setCurrentVal($current);
} elseif ($currentValueKey !== null && isset($data[$currentValueKey])) {
$contentObject->setCurrentVal($data[$currentValueKey]);
}
$content = $contentObject->parseFunc($value, null, '< ' . $parseFuncTSPath);
return $content;
}
}