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"; }