- The three market Content Blocks preview as compact collapsible rows:
thumbnail of the actual image (hero background, intro image, insights cover), key copy in the summary line, full details expanded; card and intro-paragraph previews are wrapped in the same mechanism - New SubmarketPluginPreview for vitec_usecaselist / vitec_productfeature / vitec_productlist: instead of bare standard boxes they now list the selected story titles (flagging stories that still lack a quote), the featured product and the hand-picked products in order - Container-style collapse for whole page-module COLUMNS: a chevron at the right of every column header folds a section down to its title row, state kept per page and colPos in localStorage - the slot view of a sub-market page folds to six slim bands - Previews sit under the page module's pointer-events lock and its click-to-edit layer: pointer events are re-enabled inside the collapse markup and the toggle runs on pointerdown in the capture phase - Two more v14 removals fixed on the way, both latent in the OLDER preview classes too (Usecaseshow, Modelcard would have crashed the page module): GridColumnItem::getRecord() now returns a Domain\Record object, and StandaloneView is gone - previews normalize the record via a shared helper and render through the ViewFactory
This commit is contained in:
1 parent
67be9de316
commit
78af83d2e3
12 files changed
+465
-23
No files matched your search
@@ -11,7 +11,6 @@ use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Resource\ResourceFactory;
|
||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||
|
||||
/**
|
||||
* Page-module preview for the VITEC Card plugin (vitec_modelcard):
|
||||
@@ -45,7 +44,7 @@ class ModelcardPreviewRenderer extends StandardContentPreviewRenderer
|
||||
public function renderPageModulePreviewContent(GridColumnItem $item): string
|
||||
{
|
||||
try {
|
||||
$record = $item->getRecord();
|
||||
$record = $this->recordArray($item);
|
||||
|
||||
$flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
|
||||
$flexFormData = $flexFormService->convertFlexFormContentToArray($record['pi_flexform'] ?? '');
|
||||
@@ -77,8 +76,12 @@ class ModelcardPreviewRenderer extends StandardContentPreviewRenderer
|
||||
}
|
||||
}
|
||||
|
||||
$view = GeneralUtility::makeInstance(StandaloneView::class);
|
||||
$view->setTemplatePathAndFilename('EXT:vitec/Resources/Private/Templates/Preview/Modelcard.html');
|
||||
// v14: StandaloneView was removed - views come from the ViewFactory.
|
||||
$view = GeneralUtility::makeInstance(\TYPO3\CMS\Core\View\ViewFactoryInterface::class)
|
||||
->create(new \TYPO3\CMS\Core\View\ViewFactoryData(
|
||||
templatePathAndFilename: 'EXT:vitec/Resources/Private/Templates/Preview/Modelcard.html',
|
||||
request: $GLOBALS['TYPO3_REQUEST'] ?? null,
|
||||
));
|
||||
$view->assignMultiple([
|
||||
'typeLabel' => self::TYPE_LABELS[$modelType] ?? $modelType,
|
||||
'layout' => $layout,
|
||||
@@ -124,4 +127,21 @@ class ModelcardPreviewRenderer extends StandardContentPreviewRenderer
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* v14: GridColumnItem::getRecord() returns a Domain\Record object, no
|
||||
* longer an array (found 2026-10-02 - crashed the page module preview).
|
||||
* Normalizes both shapes to the raw database array.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
private function recordArray(GridColumnItem $item): array
|
||||
{
|
||||
$record = $item->getRecord();
|
||||
if ($record instanceof \TYPO3\CMS\Core\Domain\Record) {
|
||||
$raw = $record->getRawRecord();
|
||||
return $raw !== null ? $raw->toArray() : [];
|
||||
}
|
||||
return (array)$record;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Evomedien\Vitec\Preview;
|
||||
|
||||
use TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
|
||||
/**
|
||||
* Collapsible page-module previews for the three sub-market plugin sections
|
||||
* (Olli's wish 2026-10-02: every section collapsible, content visible):
|
||||
*
|
||||
* vitec_usecaselist -> selected story titles (+ "no quote" flag)
|
||||
* vitec_productfeature -> the featured product's title
|
||||
* vitec_productlist -> hand-picked product titles / category info
|
||||
*
|
||||
* One class for all three - they only differ in how the FlexForm selection
|
||||
* is resolved to titles.
|
||||
*/
|
||||
class SubmarketPluginPreview extends StandardContentPreviewRenderer
|
||||
{
|
||||
public function renderPageModulePreviewContent(GridColumnItem $item): string
|
||||
{
|
||||
$record = $this->recordArray($item);
|
||||
$flexFormData = GeneralUtility::makeInstance(FlexFormService::class)
|
||||
->convertFlexFormContentToArray((string)($record['pi_flexform'] ?? ''));
|
||||
$settings = $flexFormData['settings'] ?? [];
|
||||
|
||||
$label = '';
|
||||
$hint = '';
|
||||
$items = [];
|
||||
switch ((string)$record['CType']) {
|
||||
case 'vitec_usecaselist':
|
||||
$layout = (string)($settings['layout'] ?? 'grid');
|
||||
$label = $layout === 'testimonials' ? 'Testimonials' : 'Success Stories';
|
||||
$uids = GeneralUtility::intExplode(',', (string)($settings['usecases'] ?? ''), true);
|
||||
foreach ($this->rows('tx_vitec_domain_model_usecase', $uids, ['quote']) as $row) {
|
||||
$items[] = $row['title'] . (trim((string)$row['quote']) === '' ? ' — ⚠ kein Zitat' : '');
|
||||
}
|
||||
$hint = $uids === [] ? 'alle Stories (' . $layout . ')' : count($items) . ' ausgewählt · ' . $layout;
|
||||
break;
|
||||
case 'vitec_productfeature':
|
||||
$label = 'Featured Product';
|
||||
$uid = (int)($settings['product'] ?? 0);
|
||||
foreach ($this->rows('tx_vitec_domain_model_product', $uid > 0 ? [$uid] : []) as $row) {
|
||||
$items[] = $row['title'];
|
||||
}
|
||||
$hint = $items[0] ?? '⚠ kein Produkt gewählt';
|
||||
break;
|
||||
case 'vitec_productlist':
|
||||
$label = 'Products';
|
||||
$uids = GeneralUtility::intExplode(',', (string)($settings['selectedproducts'] ?? ''), true);
|
||||
if ($uids !== []) {
|
||||
foreach ($this->rows('tx_vitec_domain_model_product', $uids) as $row) {
|
||||
$items[] = $row['title'];
|
||||
}
|
||||
$hint = count($items) . ' handverlesen';
|
||||
} else {
|
||||
$hint = !empty($settings['allproducts']) ? 'alle Produkte' : 'nach Kategorie';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// v14: StandaloneView was removed - views come from the ViewFactory.
|
||||
$view = GeneralUtility::makeInstance(\TYPO3\CMS\Core\View\ViewFactoryInterface::class)
|
||||
->create(new \TYPO3\CMS\Core\View\ViewFactoryData(
|
||||
templatePathAndFilename: 'EXT:vitec/Resources/Private/Templates/Preview/SubmarketSection.html',
|
||||
request: $GLOBALS['TYPO3_REQUEST'] ?? null,
|
||||
));
|
||||
$view->assignMultiple([
|
||||
'label' => $label,
|
||||
'hint' => $hint,
|
||||
'items' => $items,
|
||||
'header' => (string)($record['header'] ?? ''),
|
||||
]);
|
||||
return $view->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Title rows for the given uids, in the given order.
|
||||
*
|
||||
* @param int[] $uids
|
||||
* @param string[] $extraFields
|
||||
* @return array<int,array<string,mixed>>
|
||||
*/
|
||||
private function rows(string $table, array $uids, array $extraFields = []): array
|
||||
{
|
||||
if ($uids === []) {
|
||||
return [];
|
||||
}
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
|
||||
$rows = $queryBuilder->select('uid', 'title', ...$extraFields)->from($table)
|
||||
->where(
|
||||
$queryBuilder->expr()->in('uid', $queryBuilder->createNamedParameter($uids, Connection::PARAM_INT_ARRAY)),
|
||||
$queryBuilder->expr()->eq('deleted', 0)
|
||||
)
|
||||
->executeQuery()->fetchAllAssociative();
|
||||
$byUid = array_column($rows, null, 'uid');
|
||||
$ordered = [];
|
||||
foreach ($uids as $uid) {
|
||||
if (isset($byUid[$uid])) {
|
||||
$ordered[] = $byUid[$uid];
|
||||
}
|
||||
}
|
||||
return $ordered;
|
||||
}
|
||||
|
||||
/**
|
||||
* v14: GridColumnItem::getRecord() returns a Domain\Record object, no
|
||||
* longer an array (found 2026-10-02 - crashed the page module preview).
|
||||
* Normalizes both shapes to the raw database array.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
private function recordArray(GridColumnItem $item): array
|
||||
{
|
||||
$record = $item->getRecord();
|
||||
if ($record instanceof \TYPO3\CMS\Core\Domain\Record) {
|
||||
$raw = $record->getRawRecord();
|
||||
return $raw !== null ? $raw->toArray() : [];
|
||||
}
|
||||
return (array)$record;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ use TYPO3\CMS\Backend\Preview\StandardContentPreviewRenderer;
|
||||
use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
|
||||
use TYPO3\CMS\Core\Service\FlexFormService;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
use TYPO3\CMS\Fluid\View\StandaloneView;
|
||||
use Evomedien\Vitec\Domain\Repository\UsecaseRepository;
|
||||
|
||||
/**
|
||||
@@ -22,10 +21,14 @@ class UsecaseshowPluginPreview extends StandardContentPreviewRenderer
|
||||
*/
|
||||
public function renderPageModulePreviewContent(GridColumnItem $item): string
|
||||
{
|
||||
$record = $item->getRecord();
|
||||
$record = $this->recordArray($item);
|
||||
|
||||
$view = GeneralUtility::makeInstance(StandaloneView::class);
|
||||
$view->setTemplatePathAndFilename('EXT:vitec/Resources/Private/Templates/Preview/Usecaseshow.html');
|
||||
// v14: StandaloneView was removed - views come from the ViewFactory.
|
||||
$view = GeneralUtility::makeInstance(\TYPO3\CMS\Core\View\ViewFactoryInterface::class)
|
||||
->create(new \TYPO3\CMS\Core\View\ViewFactoryData(
|
||||
templatePathAndFilename: 'EXT:vitec/Resources/Private/Templates/Preview/Usecaseshow.html',
|
||||
request: $GLOBALS['TYPO3_REQUEST'] ?? null,
|
||||
));
|
||||
|
||||
// Parse FlexForm data
|
||||
$flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
|
||||
@@ -69,7 +72,7 @@ class UsecaseshowPluginPreview extends StandardContentPreviewRenderer
|
||||
*/
|
||||
public function renderPageModulePreviewHeader(GridColumnItem $item): string
|
||||
{
|
||||
$record = $item->getRecord();
|
||||
$record = $this->recordArray($item);
|
||||
|
||||
// Parse FlexForm to get usecase info for header
|
||||
$flexFormService = GeneralUtility::makeInstance(FlexFormService::class);
|
||||
@@ -83,4 +86,21 @@ class UsecaseshowPluginPreview extends StandardContentPreviewRenderer
|
||||
|
||||
return '<strong>🎯 Usecase Show Plugin</strong> <small style="color: orange;">(No usecase selected)</small>';
|
||||
}
|
||||
|
||||
/**
|
||||
* v14: GridColumnItem::getRecord() returns a Domain\Record object, no
|
||||
* longer an array (found 2026-10-02 - crashed the page module preview).
|
||||
* Normalizes both shapes to the raw database array.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
private function recordArray(GridColumnItem $item): array
|
||||
{
|
||||
$record = $item->getRecord();
|
||||
if ($record instanceof \TYPO3\CMS\Core\Domain\Record) {
|
||||
$raw = $record->getRawRecord();
|
||||
return $raw !== null ? $raw->toArray() : [];
|
||||
}
|
||||
return (array)$record;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user