Files
VITEC-website/migrations/fix_market_rename_regression.php
T
orascheandClaude Fable 5 90c2f97c5b Market records: delete the dropped legacy set; defuse the rename map
- vitec:align-market-records gains --delete-dropped: soft-deletes the
  records the agency dropped from the taxonomy, including their MM rows
  (DataHandler does not clean the foreign side on delete). Decision:
  all nine legacy records go, including Healthcare #42 - the Overlake
  story loses its badge on purpose and reports as unresolved on future
  importer runs
- the run exposed a regression: the RENAME_MAP entries Government ->
  Government & Agencies and Education -> Education Communications are
  not idempotent because both old names double as NEW main-market
  names. The re-run hijacked the main records (stories and teaser
  travelled along), created empty replacements and deleted the real
  sub-market records as unclaimed
- repair: migrations/fix_market_rename_regression.php (dry-run default,
  guarded) swaps the pairs back - main records keep their stories and
  workbook teasers, the fresh empties take over the sub-market roles;
  applied and verified live (marketlist 11/11 with main detail pages,
  badge distribution back to 20/9/9/8/6/4/1, no legacy names left)
- the two non-idempotent entries are removed from RENAME_MAP with a
  comment: a rename mapping whose old name is reused by the new
  taxonomy must not survive its one-time run

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-10-27 11:28:26 +01:00

122 lines
5.0 KiB
PHP

<?php
declare(strict_types=1);
/**
* Repair for the 2026-10-27 --delete-dropped run: the RENAME_MAP entries
* 'Government' -> 'Government & Agencies' and 'Education' -> 'Education
* Communications' are NOT idempotent (the old names double as the NEW main
* market names). The re-run therefore renamed the MAIN records (#50/#20,
* stories and teaser travelled along), created fresh empty "Government" /
* "Education" records, and pass 4 deleted the original (empty) sub-market
* records as unclaimed.
*
* This script swaps everything back:
* - #<main> "Government & Agencies" -> title Government, slug government,
* detail_page = page /markets/government
* - the empty record titled "Government" (created today) -> title
* Government & Agencies, slug government-agencies, detail_page =
* page /markets/government/government-and-agencies
* - same pair for Education / Education Communications
*
* Plain PDO (pattern migrations/check_bg.php). Dry-run by default.
*
* Usage: php migrations/fix_market_rename_regression.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("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]
);
function pageUid(PDO $pdo, string $slug): int
{
$stmt = $pdo->prepare('SELECT uid FROM pages WHERE deleted = 0 AND slug = ?');
$stmt->execute([$slug]);
return (int)($stmt->fetchColumn() ?: 0);
}
function record(PDO $pdo, string $title): ?array
{
$stmt = $pdo->prepare('SELECT uid, title, slug, detail_page,
(SELECT COUNT(*) FROM tx_vitec_usecase_market_mm mm WHERE mm.uid_foreign = m.uid) AS stories
FROM tx_vitec_domain_model_market m WHERE deleted = 0 AND title = ?');
$stmt->execute([$title]);
$rows = $stmt->fetchAll();
if (count($rows) !== 1) {
echo " !! " . count($rows) . " live record(s) titled \"$title\" - manual check needed\n";
return null;
}
return $rows[0];
}
$pairs = [
['mainTitle' => 'Government', 'mainSlug' => 'government', 'mainPage' => '/markets/government',
'subTitle' => 'Government & Agencies', 'subSlug' => 'government-agencies', 'subPage' => '/markets/government/government-and-agencies'],
['mainTitle' => 'Education', 'mainSlug' => 'education', 'mainPage' => '/markets/education',
'subTitle' => 'Education Communications', 'subSlug' => 'education-communications', 'subPage' => '/markets/education/education-communications'],
];
$updates = [];
foreach ($pairs as $pair) {
echo "=== {$pair['mainTitle']} ===\n";
// the record carrying the stories currently holds the SUB title
$hijacked = record($pdo, $pair['subTitle']); // ex-main, renamed today
$fresh = record($pdo, $pair['mainTitle']); // empty, created today
if ($hijacked === null || $fresh === null) {
continue;
}
$mainPageUid = pageUid($pdo, $pair['mainPage']);
$subPageUid = pageUid($pdo, $pair['subPage']);
if (!$mainPageUid || !$subPageUid) {
echo " !! page lookup failed ({$pair['mainPage']} -> $mainPageUid, {$pair['subPage']} -> $subPageUid)\n";
continue;
}
echo sprintf(" #%d \"%s\" (%d stories, slug %s, detail_page %d) -> BACK TO \"%s\" / %s / page %d\n",
$hijacked['uid'], $hijacked['title'], $hijacked['stories'], $hijacked['slug'], $hijacked['detail_page'],
$pair['mainTitle'], $pair['mainSlug'], $mainPageUid);
echo sprintf(" #%d \"%s\" (%d stories, slug %s, detail_page %d) -> BECOMES \"%s\" / %s / page %d\n",
$fresh['uid'], $fresh['title'], $fresh['stories'], $fresh['slug'], $fresh['detail_page'],
$pair['subTitle'], $pair['subSlug'], $subPageUid);
if ((int)$fresh['stories'] > 0) {
echo " !! the fresh record unexpectedly has stories - aborting this pair\n";
continue;
}
$updates[] = [(int)$hijacked['uid'], $pair['mainTitle'], $pair['mainSlug'], $mainPageUid];
$updates[] = [(int)$fresh['uid'], $pair['subTitle'], $pair['subSlug'], $subPageUid];
}
if (!$apply) {
exit("\nDRY RUN - add --apply to write.\n");
}
if ($updates === []) {
exit("\nNothing to update.\n");
}
$stmt = $pdo->prepare('UPDATE tx_vitec_domain_model_market SET title = ?, slug = ?, detail_page = ?, tstamp = UNIX_TIMESTAMP() WHERE uid = ?');
foreach ($updates as [$uid, $title, $slug, $pageUid]) {
$stmt->execute([$title, $slug, $pageUid, $uid]);
echo " updated #$uid -> \"$title\"\n";
}
echo "Done. Flush the cache, then verify the /markets marketlist and the story badges.\n";