identifier=download * in tt_content.bodytext (plain and &-encoded variants). One-time, * idempotent, dry-run by default. * * Usage: php migrations/fix_download_record_links.php (dry run) * php migrations/fix_download_record_links.php --apply */ error_reporting(E_ALL); ini_set('display_errors', '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("no project root\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] ); $needle = 'identifier=tx_vitec_download'; $rows = $pdo->query( "SELECT uid, pid, CType, LEFT(header, 40) h FROM tt_content WHERE deleted = 0 AND bodytext LIKE '%identifier=tx_vitec_download%' ORDER BY pid, uid" )->fetchAll(); echo ($apply ? "APPLY\n" : "DRY-RUN\n"); echo count($rows) . " element(s) carry the legacy identifier:\n"; foreach ($rows as $r) { printf(" #%-6d pid=%-5d %-18s %s\n", $r['uid'], $r['pid'], $r['CType'], $r['h']); } if (!$apply) { exit("DRY RUN - add --apply to rewrite identifier=tx_vitec_download -> identifier=download.\n"); } $stmt = $pdo->prepare( "UPDATE tt_content SET bodytext = REPLACE(bodytext, 'identifier=tx_vitec_download', 'identifier=download'), tstamp = UNIX_TIMESTAMP() WHERE uid = ?" ); foreach ($rows as $r) { $stmt->execute([(int)$r['uid']]); } echo count($rows) . " element(s) rewritten. Flush the cache, then re-check a story payload.\n";