Grid(s) -> naechstes Intro, danach Banner/FAQ in * bisheriger Folge) mit Stride 256 neu sortieren. * * Usage: php migrations/fix_products_grid.php (inspect) * php migrations/fix_products_grid.php --apply */ error_reporting(E_ALL); ini_set('display_errors', '1'); const PID = 447; const CONTAINERS = [11794, 11795, 11796, 11797, 11798, 11799, 11800, 11801, 11802, 11803, 11804, 11805, 11806, 11807, 11808]; const DUPLICATES = [ 11861, 11862, 11863, 11864, 11865, 11866, 11867, 11868, 11869, 11870, 11871, 11872, 11873, 11874, 11875, 11876, 11877, 11878, 11879, 11880, 11881, 11882, 11883, 11884, 11885, 11886, 11887, 11888, 11889, 11890, 11891, 11892, 11893, 11894, 11895, 11896, 11897, 11898, ]; // Zielreihenfolge colPos0: Sektions-Intro, danach seine Grids (Zuordnung // ueber die Container-Kinder verifiziert, check_grid_447-Ausgabe 2026-10-28) const ORDER = [ 11741, 11808, 11807, // IPTV & Digital Signage (5 Karten -> 2 Grids) 11747, 11806, 11805, 11804, // Video Encoding & Streaming (7 -> 3) 11755, 11803, // Gateways & Transcoding (3 -> 1) 11759, 11802, 11801, // Control Room Platforms (6 -> 2) 11766, 11800, // AV over IP & KVM (2 -> 1) 11769, 11799, 11798, // Video Wall & Display Processing (4 -> 2) 11774, 11797, // Graphics & Multi-Display (2 -> 1) 11777, 11796, 11795, // Video Capture (6 -> 2) 11784, 11794, // Infrastructure & Accessories (3 -> 1) ]; $apply = in_array('--apply', $argv, true); $root = null; $dir = __DIR__; for ($i = 0; $i < 5; $i++) { if (is_file($dir . '/config/system/settings.php')) { $root = $dir; break; } $dir = dirname($dir); } if ($root === null) { exit("Could not locate project root above " . __DIR__ . "\n"); } $settings = require $root . '/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' : 'INSPECT') . " ยท pid " . PID . "\n\n"; // Sanity: alle ORDER-/CONTAINER-uids existieren undeleted auf der Seite $rows = $pdo->query('SELECT uid, CType, colPos, hidden, LEFT(header,40) h FROM tt_content WHERE deleted = 0 AND pid = ' . PID)->fetchAll(); $byUid = []; foreach ($rows as $row) { $byUid[(int)$row['uid']] = $row; } foreach (array_merge(ORDER, DUPLICATES) as $uid) { if (!isset($byUid[$uid])) { exit("ABBRUCH: uid $uid fehlt auf der Seite (geloescht/verschoben?) - erst klaeren.\n"); } } // Rest von colPos0 (Banner, FAQ, ...) hinten anhaengen, bisherige Folge $tail = []; foreach ($pdo->query('SELECT uid, CType, LEFT(header,40) h FROM tt_content WHERE deleted = 0 AND pid = ' . PID . ' AND colPos = 0 ORDER BY sorting, uid') as $row) { $uid = (int)$row['uid']; if (!in_array($uid, ORDER, true) && !in_array($uid, DUPLICATES, true)) { $tail[] = $uid; echo "tail: #$uid {$row['CType']} \"{$row['h']}\"\n"; } } echo "\n1) " . count(CONTAINERS) . " Container einblenden (hidden=0): " . implode(',', CONTAINERS) . "\n"; echo "2) " . count(DUPLICATES) . " Duplikat-Karten soft-loeschen: " . implode(',', DUPLICATES) . "\n"; echo "3) colPos0 neu sortieren: " . count(ORDER) . " Elemente in P5-Folge + " . count($tail) . " Tail-Element(e)\n"; $sequence = array_merge(ORDER, $tail); foreach ($sequence as $i => $uid) { $r = $byUid[$uid]; printf(" %3d. #%-6d %-22s %s\n", $i + 1, $uid, $r['CType'], $r['h']); } if (!$apply) { echo "\nInspect only - mit --apply schreiben.\n"; exit(0); } $pdo->exec('UPDATE tt_content SET hidden = 0, tstamp = UNIX_TIMESTAMP() WHERE uid IN (' . implode(',', CONTAINERS) . ')'); $pdo->exec('UPDATE tt_content SET deleted = 1, tstamp = UNIX_TIMESTAMP() WHERE uid IN (' . implode(',', DUPLICATES) . ')'); $sorting = 0; $stmt = $pdo->prepare('UPDATE tt_content SET sorting = ?, tstamp = UNIX_TIMESTAMP() WHERE uid = ?'); foreach ($sequence as $uid) { $sorting += 256; $stmt->execute([$sorting, $uid]); } echo "\nGeschrieben. Danach: vendor/bin/typo3 cache:flush\n";