We often use 3 different ViewHelpers in the fluid
- exception.catch It can happen that you want to render an image, for example, but the editor has not maintained it. This would result in an exception via the Image-ViewHelper. This is bad because the editor can then no longer edit the entire page in the backend. Therefore we catch these errors and show them in the preview.
- backend.editLink If you want to click somewhere on the preview and the editing view should open, you can use this ViewHelper.
- backend.removeLinks If you want to display text from an RTE, it can happen that A tags are rendered. But especially if you have set an external link with backend.editLink, you do not want to create further links.
{namespace in2template=In2code\In2template\ViewHelpers}
<in2template:exception.catch>
<in2template:backend.editLink identifier="{data.uid}">
<div class="in2template-preview-stage" style="background-image: url({f:uri.image(image:firstImage,width:'2000m')});">
<div class="in2template-preview-stage-box">
<h1>{data.header}</h1>
<in2template:backend.removeLinks>{data.bodytext}</in2template:backend.removeLinks>
<p>
<span class="btn">{data.button_label}</span>
</p>
</div>
</div>
</in2template:backend.editLink>
</in2template:exception.catch>
EXT:in2template/Classes/ViewHelpers/Exception/CatchViewHelper.php:
<?php
declare(strict_types=1);
namespace In2code\In2template\ViewHelpers\Exception;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
class CatchViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
public function render(): string
{
try {
return $this->renderChildren();
} catch (\Exception $exception) {
$string = '<div class="alert alert-danger" role="alert">';
$string .= $exception->getMessage();
$string .= ' (' . $exception->getCode() . ')';
$string .= '</div>';
return $string;
}
}
}
EXT:in2template/Classes/ViewHelpers/Backend/EditLinkViewHelper.php:
<?php
declare(strict_types=1);
namespace In2code\In2template\ViewHelpers\Backend;
use In2code\In2template\Utility\BackendUtility;
use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
class EditLinkViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('identifier', 'int', 'Identifier', true);
$this->registerArgument('table', 'string', 'Tablename', false, 'tt_content');
}
public function render(): string
{
$string = '<a href="';
$string .= BackendUtility::createEditUri($this->arguments['table'], (int)$this->arguments['identifier']);
$string .= '" class="in2template_editlink">';
$string .= $this->renderChildren();
$string .= '</a>';
return $string;
}
}
Hierzu braucht es noch eine EXT:in2template/Classes/Utility/BackendUtility.php:
<?php
declare(strict_types=1);
namespace In2code\In2template\Utility;
use TYPO3\CMS\Backend\Routing\Exception\ResourceNotFoundException;
use TYPO3\CMS\Backend\Routing\Exception\RouteNotFoundException;
use TYPO3\CMS\Backend\Routing\Router;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class BackendUtility
{
public static function createEditUri(string $tableName, int $identifier, bool $addReturnUrl = true): string
{
$uriParameters = [
'edit' => [
$tableName => [
$identifier => 'edit'
]
]
];
if ($addReturnUrl) {
$uriParameters['returnUrl'] = self::getReturnUrl();
}
return self::getRoute('record_edit', $uriParameters);
}
protected static function getReturnUrl(): string
{
return self::getRoute(self::getModuleName(), self::getCurrentParameters());
}
public static function getRoute(string $route, array $parameters = []): string
{
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
return (string)$uriBuilder->buildUriFromRoute($route, $parameters);
}
protected static function getModuleName(): string
{
$moduleName = 'record_edit';
if (GeneralUtility::_GET('route') !== null) {
$routePath = (string)GeneralUtility::_GET('route');
$router = GeneralUtility::makeInstance(Router::class);
try {
$route = $router->match($routePath);
$moduleName = $route->getOption('_identifier');
} catch (ResourceNotFoundException $exception) {
unset($exception);
}
}
return $moduleName;
}
public static function getCurrentParameters(array $getParameters = []): array
{
if (empty($getParameters)) {
$getParameters = GeneralUtility::_GET();
}
$parameters = [];
$ignoreKeys = [
'M',
'moduleToken',
'route',
'token'
];
foreach ($getParameters as $key => $value) {
if (in_array($key, $ignoreKeys)) {
continue;
}
$parameters[$key] = $value;
}
return $parameters;
}
}
EXT:in2template/Classes/ViewHelpers/Backend/RemoveLinksViewHelper.php:
<?php
declare(strict_types=1);
namespace In2code\In2template\ViewHelpers\Backend;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
class RemoveLinksViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
protected $style = 'color: #A5C85A; font-weight: bold; text-decoration: underline;';
public function render(): string
{
$string = html_entity_decode($this->renderChildren());
$dom = new \DOMDocument();
@$dom->loadHTML(
$this->wrapHtmlWithMainTags($string),
LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
);
$aTags = $dom->getElementsByTagName('a');
while ($aTags->length) {
$aTag = $aTags[0];
$linkText = $aTag->nodeValue;
$class = $aTag->getAttribute('class');
$span = $dom->createElement('span');
$span->setAttribute('class', $class);
$span->setAttribute('style', $this->style);
$span->nodeValue = $linkText;
$aTag->parentNode->replaceChild($span, $aTag);
}
return $this->stripMainTagsFromHtml($dom->saveHTML());
}
protected function wrapHtmlWithMainTags(string $html): string
{
return '<?xml encoding="utf-8" ?><html><body>' . $html . '</body></html>';
}
protected function stripMainTagsFromHtml(string $html): string
{
return str_replace(['<html>', '</html>', '<body>', '</body>', '<?xml encoding="utf-8" ?>'], '', $html);
}
}