Checkpoint: headless JSON architecture documented + cleanup (Stufe 1+2)
Restore point before Stufe 3 (central resolver-service refactoring). Includes this session's work: - Success Story (usecase) rebuild: new fields/tabs, UsecaseSerializer, thin List/Show renderers, MM relations, inline content elements. - vitec_columns content block (two-column layout with per-item content) incl. unified header section; special-cased JSON resolution. - Container per-column flex (items[].config align/justify) + gap on parent. - Unified header section across CEs/plugins/containers; header fields in JSON. - ISO-style architecture spec: Documentation/Headless-JSON-Architecture.md. - Cleanup: removed local scratch + verified .bak backups. - Fixes: B-6 (undefined thumbnail variable in Downloadcardcollection image resolver), B-7 (unsatisfiable legacy CType OR branch in Downloadcard/Datasheets). Rollback: git reset --hard snapshot-2026-07-09-pre-stufe3 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
61
packages/vitec/Classes/DataProcessing/ContainerChildrenProcessor.php
Executable file → Normal file
61
packages/vitec/Classes/DataProcessing/ContainerChildrenProcessor.php
Executable file → Normal file
@@ -12,6 +12,8 @@ use Evomedien\Vitec\UserFunc\SolutionShowJsonRenderer;
|
||||
use Evomedien\Vitec\UserFunc\DownloadcardJsonRenderer;
|
||||
use Evomedien\Vitec\UserFunc\DownloadcardcollectionJsonRenderer;
|
||||
use Evomedien\Vitec\UserFunc\DatasheetsJsonRenderer;
|
||||
use Evomedien\Vitec\UserFunc\EventlistJsonRenderer;
|
||||
use Evomedien\Vitec\UserFunc\NewsJsonRenderer;
|
||||
use TYPO3\CMS\Core\Database\Connection;
|
||||
use TYPO3\CMS\Core\Database\ConnectionPool;
|
||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||
@@ -20,9 +22,13 @@ use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
|
||||
|
||||
/**
|
||||
* Collect container children grouped by colPos and emit a lean, transport-
|
||||
* ready structure. Each child is normalised to:
|
||||
* { id, type, colPos, sorting, appearance, data }
|
||||
* `data` only contains non-empty content-relevant fields.
|
||||
* ready structure. Each column is normalised to:
|
||||
* { config: { colPos, align, justify }, contentElements: [ { id, type, … } ] }
|
||||
* `align`/`justify` are the PARENT container's per-column flex settings
|
||||
* (tx_vitec_col{N}_align/justify) and therefore apply to ALL children of that
|
||||
* column. Each child is normalised to { id, type, colPos, sorting, appearance,
|
||||
* data }, where `data` only contains non-empty content-relevant fields —
|
||||
* container-level fields (gap, col flex) are never leaked to children.
|
||||
*
|
||||
* VITEC list-plugins nested as container children (productlist, productshow,
|
||||
* usecaselist, usecaseshow) are resolved to the SAME JSON the top-level
|
||||
@@ -59,6 +65,30 @@ final class ContainerChildrenProcessor implements DataProcessorInterface
|
||||
'uploads_description', 'uploads_type',
|
||||
];
|
||||
|
||||
/**
|
||||
* Container-level fields — they belong on the parent container (grid gap
|
||||
* and per-column flex) and must never appear in a child's `data`.
|
||||
*/
|
||||
private const CONTAINER_FIELDS = [
|
||||
'tx_vitec_gap',
|
||||
'tx_vitec_col1_align', 'tx_vitec_col1_justify',
|
||||
'tx_vitec_col2_align', 'tx_vitec_col2_justify',
|
||||
'tx_vitec_col3_align', 'tx_vitec_col3_justify',
|
||||
'tx_vitec_col4_align', 'tx_vitec_col4_justify',
|
||||
];
|
||||
|
||||
/**
|
||||
* Per container CType: colPos value => 1-based column number. Used to pick
|
||||
* the parent's tx_vitec_col{N}_align/justify for each rendered column.
|
||||
*/
|
||||
private const COLPOS_TO_COLUMN = [
|
||||
'vitec_cols_50_50' => [211 => 1, 212 => 2],
|
||||
'vitec_cols_33_66' => [251 => 1, 252 => 2],
|
||||
'vitec_cols_66_33' => [241 => 1, 242 => 2],
|
||||
'vitec_cols_33_33_33' => [221 => 1, 222 => 2, 223 => 3],
|
||||
'vitec_cols_25_25_25_25' => [231 => 1, 232 => 2, 233 => 3, 234 => 4],
|
||||
];
|
||||
|
||||
/** Fields whose 0/empty value is still meaningful. */
|
||||
private const KEEP_IF_ZERO = [
|
||||
'header_layout',
|
||||
@@ -80,6 +110,16 @@ final class ContainerChildrenProcessor implements DataProcessorInterface
|
||||
'vitec_downloadcard' => [DownloadcardJsonRenderer::class, 'downloadcard'],
|
||||
'vitec_downloadcardcollection' => [DownloadcardcollectionJsonRenderer::class, 'downloadcardcollection'],
|
||||
'vitec_datasheets' => [DatasheetsJsonRenderer::class, 'datasheets'],
|
||||
'vitec_eventlist' => [EventlistJsonRenderer::class, 'eventlist'],
|
||||
'news_pi1' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_newsliststicky' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_newsselectedlist' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_newsdetail' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_newsdatemenu' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_categorylist' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_newssearchform' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_newssearchresult' => [NewsJsonRenderer::class, 'news'],
|
||||
'news_taglist' => [NewsJsonRenderer::class, 'news'],
|
||||
];
|
||||
|
||||
public function process(
|
||||
@@ -121,10 +161,20 @@ final class ContainerChildrenProcessor implements DataProcessorInterface
|
||||
}
|
||||
ksort($byColPos);
|
||||
|
||||
// Per-column flex settings come from the parent container record.
|
||||
$parentCType = (string)($cObj->data['CType'] ?? '');
|
||||
$colMap = self::COLPOS_TO_COLUMN[$parentCType] ?? [];
|
||||
|
||||
$items = [];
|
||||
foreach ($byColPos as $colPos => $contentElements) {
|
||||
$config = ['colPos' => $colPos];
|
||||
$columnNo = $colMap[$colPos] ?? null;
|
||||
if ($columnNo !== null) {
|
||||
$config['align'] = (string)($cObj->data['tx_vitec_col' . $columnNo . '_align'] ?? 'stretch');
|
||||
$config['justify'] = (string)($cObj->data['tx_vitec_col' . $columnNo . '_justify'] ?? 'flex-start');
|
||||
}
|
||||
$items[] = [
|
||||
'config' => ['colPos' => $colPos],
|
||||
'config' => $config,
|
||||
'contentElements' => $contentElements,
|
||||
];
|
||||
}
|
||||
@@ -147,6 +197,9 @@ final class ContainerChildrenProcessor implements DataProcessorInterface
|
||||
if (in_array($field, self::SYSTEM_FIELDS, true)) {
|
||||
continue;
|
||||
}
|
||||
if (in_array($field, self::CONTAINER_FIELDS, true)) {
|
||||
continue;
|
||||
}
|
||||
if ($this->isEmpty($value) && !in_array($field, self::KEEP_IF_ZERO, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user