Why-VITEC-Band auf den 3 alten Kategorieseiten (0106-FE, Entscheidung Harry)

migrations/why_band_unwrap_20261111.php: loest die vitec_cols-Container
hinter dem Why-VITEC-Intro auf graphics-and-multi-display,
infrastructure-and-accessories und video-capture auf, stellt die 12 Karten
als icon_card top-level hinter das Intro und sortiert die Hauptspalte neu
(Inspect default, --apply). Angewandt, Seiten gepurgt und gewaermt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
orascheandClaude Fable 5.1 committed 2026-11-11 10:25:29 +01:00
1 parent 086a178341
commit 8cdcd99eb3
1 file changed
+161
+161
View File
@@ -0,0 +1,161 @@
<?php
/**
* why_band_unwrap_20261111.php (Ticket 0106-FE, Abschnitt "alte Seiten")
*
* Die drei 2026-10-Kategorieseiten ohne Menueplatz tragen ihre "Why VITEC?"-
* Karten noch als `vertical`-Karten IN vitec_cols_33_33_33-Containern
* (wrap-cards-grid vom 27.10.). Das Frontend baut das Icon-Band (0039-BE)
* aber nur aus `vitec_card` mit layout_variant icon_card DIREKT hinter dem
* Intro. Entscheidung Harry 2026-11-11: diese Seiten bekommen das Band auch.
*
* Umbau je Seite: Intro "Why VITEC?" finden, die direkt folgenden Container
* (nur solche, die ausschliesslich vitec_card enthalten) aufloesen - Karten
* nach colPos 0 / tx_container_parent 0 / icon_card, leere Container soft-
* loeschen, colPos 0 mit Stride 256 neu sortieren (Band direkt hinter dem
* Intro, Rest in bisheriger Folge). Direktes SQL -> Auto-Purge greift NICHT:
* danach cache:flush + vitec:ssr-purge/-warm mit den Pfaden.
*
* php migrations/why_band_unwrap_20261111.php # INSPECT (default)
* php migrations/why_band_unwrap_20261111.php --apply # schreibt
*/
declare(strict_types=1);
$apply = in_array('--apply', $argv, true);
$settings = require __DIR__ . '/../config/system/settings.php';
$db = $settings['DB']['Connections']['Default'];
$pdo = new PDO(
sprintf('mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4', $db['host'] ?? 'localhost', $db['port'] ?? 3306, $db['dbname'] ?? ''),
$db['user'] ?? '', $db['password'] ?? '',
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]
);
echo $apply ? "APPLY\n\n" : "INSPECT - nichts wird geschrieben (--apply zum Schreiben)\n\n";
$slugs = [
'/products/graphics-and-multi-display',
'/products/infrastructure-and-accessories',
'/products/video-capture',
];
$norm = static fn(string $s): string => (string)preg_replace('/[^a-z0-9]+/', '', strtolower($s));
$done = 0;
foreach ($slugs as $slug) {
$st = $pdo->prepare('SELECT uid, title FROM pages WHERE deleted = 0 AND slug = ? AND sys_language_uid = 0');
$st->execute([$slug]);
$page = $st->fetch();
if (!$page) {
echo "$slug: Seite NICHT gefunden - uebersprungen\n\n";
continue;
}
$pid = (int)$page['uid'];
$st = $pdo->prepare(
'SELECT uid, CType, header, sorting, vitec_layout_variant FROM tt_content
WHERE pid = ? AND deleted = 0 AND colPos = 0 AND sys_language_uid = 0
AND (tx_container_parent IS NULL OR tx_container_parent = 0)
ORDER BY sorting, uid'
);
$st->execute([$pid]);
$top = $st->fetchAll();
echo "== $slug (pid $pid) \"{$page['title']}\" - " . count($top) . " Top-Level-Elemente in colPos 0\n";
// bereits umgebaut? (Band = Intro + direkt folgende Karten top-level)
$whyIdx = null;
foreach ($top as $i => $el) {
if ($el['CType'] === 'vitec_introparagraph' && str_starts_with($norm((string)$el['header']), 'whyvitec')) {
$whyIdx = $i;
break;
}
}
if ($whyIdx === null) {
echo " kein Why-VITEC-Intro gefunden - uebersprungen\n\n";
continue;
}
$intro = $top[$whyIdx];
if (isset($top[$whyIdx + 1]) && $top[$whyIdx + 1]['CType'] === 'vitec_card') {
echo " Band liegt bereits top-level hinter Intro #{$intro['uid']} - nichts zu tun\n\n";
continue;
}
// direkt folgende Container einsammeln, solange sie nur Karten enthalten
$containers = [];
$cards = [];
for ($i = $whyIdx + 1; $i < count($top); $i++) {
$el = $top[$i];
if (!str_starts_with((string)$el['CType'], 'vitec_cols')) {
break;
}
$kids = $pdo->query(
'SELECT uid, CType, header, colPos, sorting, vitec_layout_variant FROM tt_content
WHERE deleted = 0 AND tx_container_parent = ' . (int)$el['uid'] . ' ORDER BY colPos, sorting, uid'
)->fetchAll();
$onlyCards = $kids !== [] && count(array_filter($kids, static fn(array $k): bool => $k['CType'] !== 'vitec_card')) === 0;
if (!$onlyCards) {
break;
}
$containers[] = $el;
foreach ($kids as $k) {
$cards[] = $k;
}
}
if ($cards === []) {
echo " Intro #{$intro['uid']} \"{$intro['header']}\" ohne folgende Karten-Container - uebersprungen\n\n";
continue;
}
printf(" Intro #%d \"%s\"\n", $intro['uid'], $intro['header']);
printf(" %d Container (#%s) mit %d Karte(n):\n", count($containers), implode(', #', array_column($containers, 'uid')), count($cards));
foreach ($cards as $c) {
printf(" #%-6d %-14s \"%s\"\n", $c['uid'], (string)$c['vitec_layout_variant'], (string)$c['header']);
}
// neue Reihenfolge: bis Intro, dann Karten, dann Rest ohne die Container
$containerUids = array_map('intval', array_column($containers, 'uid'));
$newOrder = [];
foreach ($top as $i => $el) {
if (in_array((int)$el['uid'], $containerUids, true)) {
continue;
}
$newOrder[] = ['uid' => (int)$el['uid'], 'label' => $el['CType'] . ' ' . $el['header']];
if ($i === $whyIdx) {
foreach ($cards as $c) {
$newOrder[] = ['uid' => (int)$c['uid'], 'label' => 'vitec_card (icon_card) ' . $c['header']];
}
}
}
echo " Neue Reihenfolge colPos 0:\n";
$sorting = 0;
foreach ($newOrder as $el) {
$sorting += 256;
printf(" %5d #%-6d %s\n", $sorting, $el['uid'], $el['label']);
}
if ($apply) {
$pdo->beginTransaction();
$upCard = $pdo->prepare("UPDATE tt_content SET colPos = 0, tx_container_parent = 0, vitec_layout_variant = 'icon_card', tstamp = UNIX_TIMESTAMP() WHERE uid = ?");
foreach ($cards as $c) {
$upCard->execute([(int)$c['uid']]);
}
$pdo->exec('UPDATE tt_content SET deleted = 1, tstamp = UNIX_TIMESTAMP() WHERE uid IN (' . implode(',', $containerUids) . ')');
$upSort = $pdo->prepare('UPDATE tt_content SET sorting = ?, tstamp = UNIX_TIMESTAMP() WHERE uid = ?');
$sorting = 0;
foreach ($newOrder as $el) {
$sorting += 256;
$upSort->execute([$sorting, $el['uid']]);
}
$pdo->commit();
echo " GESCHRIEBEN\n";
}
$done++;
echo "\n";
}
echo ($apply ? 'FERTIG' : 'WUERDE') . ": $done Seite(n) umgebaut.\n";
if ($apply && $done > 0) {
echo "Danach: vendor/bin/typo3 cache:flush && vendor/bin/typo3 vitec:ssr-purge " . implode(' ', $slugs) . " && vendor/bin/typo3 vitec:ssr-warm " . implode(' ', $slugs) . "\n";
}