feat: page module previews for teasers, disrupter, disturber, map and lineup
The TYPO3 10 drawItem hooks become one preview renderer registered per
CType in TCA; it renders the old templates from a46918d with the same
variables (f:format.html is not allowed in the backend: f:sanitize.html).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
44614a4a75
commit
0b17a24edd
13 files changed
+355
No files matched your search
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace EP\EpTheme\Preview;
|
||||
|
||||
use TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer;
|
||||
use TYPO3\CMS\Backend\Utility\BackendUtility;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Resource\FileRepository;
|
||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Core\View\ViewFactoryData;
|
||||
use TYPO3\CMS\Core\View\ViewFactoryInterface;
|
||||
|
||||
/**
|
||||
* Page module previews of the theme's content elements, rendered from
|
||||
* Templates/PreviewRenderer/<CType>.html as the TYPO3 10 drawItem hooks did
|
||||
* (Classes/Hooks/PageLayoutView in a46918d), with the same template variables.
|
||||
* Registered per CType in TCA (['types'][<CType>]['previewRenderer']).
|
||||
*/
|
||||
class ContentPreviewRenderer extends StandardContentPreviewRenderer
|
||||
{
|
||||
/**
|
||||
* CType => [field holding the related uid, related table, template variable]
|
||||
*/
|
||||
protected const RELATED_RECORDS = [
|
||||
'teaser_country' => ['tx_eptheme_context_country', 'tx_epproducts_domain_model_country', 'country'],
|
||||
'teaser_region' => ['tx_eptheme_context_region', 'tx_epproducts_domain_model_region', 'region'],
|
||||
'teaser_city' => ['tx_eptheme_context_city', 'tx_epproducts_domain_model_city', 'city'],
|
||||
'teaser_hotel' => ['tx_eptheme_context_hotel', 'tx_epproducts_domain_model_hotel', 'hotel'],
|
||||
'teaser_concept' => ['tx_eptheme_context_concept', 'tx_epproducts_domain_model_concept', 'concept'],
|
||||
'teaser_product' => ['tx_eptheme_context_product', 'tx_epproducts_domain_model_product', 'product'],
|
||||
'teaser_booking_link' => ['tx_eptheme_context_product', 'tx_epproducts_domain_model_product', 'product'],
|
||||
];
|
||||
|
||||
public function renderPageModulePreviewContent(GridColumnItem $item): string
|
||||
{
|
||||
$row = $item->getRecord();
|
||||
$cType = (string)$row['CType'];
|
||||
$template = GeneralUtility::getFileAbsFileName(
|
||||
'EXT:ep_theme/Resources/Private/Templates/PreviewRenderer/' . GeneralUtility::underscoredToUpperCamelCase($cType) . '.html'
|
||||
);
|
||||
if (!is_file($template)) {
|
||||
return parent::renderPageModulePreviewContent($item);
|
||||
}
|
||||
|
||||
$images = $this->getImages((int)$row['uid'], 'tt_content', 'image');
|
||||
$variables = [
|
||||
'data' => $row,
|
||||
'flexForm' => GeneralUtility::makeInstance(FlexFormService::class)->convertFlexFormContentToArray((string)($row['pi_flexform'] ?? '')),
|
||||
'firstImage' => $images[0] ?? null,
|
||||
'images' => $images,
|
||||
];
|
||||
$variables = array_replace($variables, $this->getAssignmentsForTemplate($cType, $row));
|
||||
|
||||
$view = GeneralUtility::makeInstance(ViewFactoryInterface::class)->create(new ViewFactoryData(
|
||||
templatePathAndFilename: $template,
|
||||
request: $item->getContext()->getCurrentRequest(),
|
||||
));
|
||||
$view->assignMultiple($variables);
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
protected function getAssignmentsForTemplate(string $cType, array $row): array
|
||||
{
|
||||
if (isset(self::RELATED_RECORDS[$cType])) {
|
||||
[$field, $table, $name] = self::RELATED_RECORDS[$cType];
|
||||
$uid = (int)($row[$field] ?? 0);
|
||||
$assignments = [
|
||||
'images' => $this->getImages($uid, $table, 'teaser_images'),
|
||||
$name => $uid > 0 ? BackendUtility::getRecord($table, $uid) : null,
|
||||
];
|
||||
if ($cType === 'teaser_product') {
|
||||
$hotelUid = (int)($row['tx_eptheme_context_hotel'] ?? 0);
|
||||
$assignments['hotel'] = $hotelUid > 0 ? BackendUtility::getRecord('tx_epproducts_domain_model_hotel', $hotelUid) : null;
|
||||
}
|
||||
return $assignments;
|
||||
}
|
||||
|
||||
switch ($cType) {
|
||||
case 'gmap':
|
||||
$regionUid = (int)($row['tx_eptheme_context_region'] ?? 0);
|
||||
$content = $regionUid > 0
|
||||
? BackendUtility::getRecord('tx_epproducts_domain_model_region', $regionUid)
|
||||
: BackendUtility::getRecord('tx_epproducts_domain_model_hotel', (int)($row['tx_eptheme_context_hotel'] ?? 0));
|
||||
return ['content' => $content];
|
||||
case 'disrupter':
|
||||
// tx_eptheme_disrupter is an MM relation; the field itself only holds the count
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_eptheme_ttcontent_tx_eptheme_disrupter_mm');
|
||||
$disrupterUid = (int)$queryBuilder->select('uid_foreign')
|
||||
->from('tx_eptheme_ttcontent_tx_eptheme_disrupter_mm')
|
||||
->where($queryBuilder->expr()->eq('uid_local', $queryBuilder->createNamedParameter((int)$row['uid'])))
|
||||
->orderBy('sorting')
|
||||
->setMaxResults(1)
|
||||
->executeQuery()
|
||||
->fetchOne();
|
||||
return ['content' => $disrupterUid > 0 ? BackendUtility::getRecord('tx_eptheme_domain_model_disrupter', $disrupterUid) : null];
|
||||
case 'lineup':
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_eptheme_domain_model_lineup');
|
||||
$rows = $queryBuilder->select('*')
|
||||
->from('tx_eptheme_domain_model_lineup')
|
||||
->where($queryBuilder->expr()->eq('tt_content', $queryBuilder->createNamedParameter((int)$row['uid'])))
|
||||
->orderBy('sorting')
|
||||
->executeQuery()
|
||||
->fetchAllAssociative();
|
||||
return ['rows' => $rows];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getImages(int $uid, string $table, string $field): array
|
||||
{
|
||||
if ($uid <= 0) {
|
||||
return [];
|
||||
}
|
||||
return GeneralUtility::makeInstance(FileRepository::class)->findByRelation($table, $field, $uid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
use EP\EpTheme\Preview\ContentPreviewRenderer;
|
||||
|
||||
defined('TYPO3') or die();
|
||||
|
||||
// Page module previews (Templates/PreviewRenderer/<CType>.html); loads after tt_content_element_*.php
|
||||
foreach (['teaser_country', 'teaser_region', 'teaser_city', 'teaser_hotel', 'teaser_concept', 'teaser_product',
|
||||
'teaser_booking_link', 'gmap', 'disturber', 'disrupter', 'lineup'] as $cType) {
|
||||
if (isset($GLOBALS['TCA']['tt_content']['types'][$cType])) {
|
||||
$GLOBALS['TCA']['tt_content']['types'][$cType]['previewRenderer'] = ContentPreviewRenderer::class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Störer</strong>
|
||||
</p>
|
||||
<strong>
|
||||
{content.headline}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Störer</strong>
|
||||
</p>
|
||||
<strong>
|
||||
<f:switch expression="{data.layout}">
|
||||
<f:case value="1">
|
||||
groß
|
||||
</f:case>>
|
||||
<f:case value="2">
|
||||
Event klein
|
||||
</f:case>
|
||||
<f:case value="3">
|
||||
Event groß
|
||||
</f:case>
|
||||
<f:defaultCase>
|
||||
klein
|
||||
</f:defaultCase>
|
||||
</f:switch>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,11 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>OSM Karte</strong>
|
||||
</p>
|
||||
<strong>
|
||||
{content.name} ({content.latitude}, {content.longitude})
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,15 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Lineup</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<f:for each="{rows}" as="row">
|
||||
<li>
|
||||
{row.name}
|
||||
</li>
|
||||
</f:for>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Teaser Buchungslink</strong>
|
||||
</p>
|
||||
<p>
|
||||
<f:if condition="{images.0}">
|
||||
<f:then>
|
||||
<f:image image="{images.0.originalFile}" width="200" height="80c" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png" width="200" height="80c"/>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</p>
|
||||
<strong>
|
||||
{product.name}
|
||||
</strong>
|
||||
<br>
|
||||
{product.teaser -> f:sanitize.html()}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Teaser Ort</strong>
|
||||
</p>
|
||||
<p>
|
||||
<f:if condition="{images.0}">
|
||||
<f:then>
|
||||
<f:image image="{images.0.originalFile}" width="200" height="80c" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png" width="200" height="80c"/>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</p>
|
||||
<strong>
|
||||
{city.name}
|
||||
</strong>
|
||||
<br>
|
||||
{city.teaser -> f:sanitize.html()}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Teaser Konzept</strong>
|
||||
</p>
|
||||
<p>
|
||||
<f:if condition="{images.0}">
|
||||
<f:then>
|
||||
<f:image image="{images.0.originalFile}" width="200" height="80c" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png" width="200" height="80c"/>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</p>
|
||||
<strong>
|
||||
{concept.name}
|
||||
</strong>
|
||||
<br>
|
||||
{concept.teaser -> f:sanitize.html()}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Teaser Land</strong>
|
||||
</p>
|
||||
<p>
|
||||
<f:if condition="{images.0}">
|
||||
<f:then>
|
||||
<f:image image="{images.0.originalFile}" width="200" height="80c" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png" width="200" height="80c"/>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</p>
|
||||
<strong>
|
||||
{country.name}
|
||||
</strong>
|
||||
<br>
|
||||
{country.teaser -> f:sanitize.html()}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Teaser Hotel</strong>
|
||||
</p>
|
||||
<p>
|
||||
<f:if condition="{images.0}">
|
||||
<f:then>
|
||||
<f:image image="{images.0.originalFile}" width="200" height="80c" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png" width="200" height="80c"/>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</p>
|
||||
<strong>
|
||||
{hotel.name}
|
||||
</strong>
|
||||
<br>
|
||||
{hotel.teaser -> f:sanitize.html()}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Teaser Produkt</strong>
|
||||
</p>
|
||||
<p>
|
||||
<f:if condition="{images.0}">
|
||||
<f:then>
|
||||
<f:image image="{images.0.originalFile}" width="200" height="80c" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png" width="200" height="80c"/>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</p>
|
||||
<strong>
|
||||
{product.name}
|
||||
</strong>
|
||||
<br>
|
||||
{product.teaser -> f:sanitize.html()}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
{namespace be=TYPO3\CMS\Backend\ViewHelpers}
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p>
|
||||
<strong>Teaser Gebiet</strong>
|
||||
</p>
|
||||
<p>
|
||||
<f:if condition="{images.0}">
|
||||
<f:then>
|
||||
<f:image image="{images.0.originalFile}" width="200" height="80c" />
|
||||
</f:then>
|
||||
<f:else>
|
||||
<f:image src="EXT:ep_theme/Resources/Public/images/lazy.png" width="200" height="80c"/>
|
||||
</f:else>
|
||||
</f:if>
|
||||
</p>
|
||||
<strong>
|
||||
{region.name}
|
||||
</strong>
|
||||
<br>
|
||||
{region.teaser -> f:sanitize.html()}
|
||||
</div>
|
||||
</div>
|
||||
Reference in new issue
Block a user