PHP Classes

File: scripts/backfill_message_charset.php

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   scripts/backfill_message_charset.php   Download  
File: scripts/backfill_message_charset.php
Role: Example script
Content type: text/plain
Description: Example script
Class: Binkterm PHP
Bulletin board system based on the Web
Author: By
Last change:
Date: 5 days ago
Size: 4,419 bytes
 

Contents

Class file image Download
#!/usr/bin/env php
<?php
/**
 * backfill_message_charset.php - Populate message_charset from the CHRS kludge
 *
 * Finds echomail and netmail rows where message_charset IS NULL, extracts the
 * CHRS kludge from kludge_lines, normalises the value via
 * BinkpConfig::normalizeCharset(), and writes it back to message_charset.
 *
 * Rows with no kludge_lines or no CHRS kludge are left untouched.
 *
 * Runs as a DRY RUN by default. Pass --live to apply changes.
 *
 * Usage:
 * php scripts/backfill_message_charset.php # dry run
 * php scripts/backfill_message_charset.php --live # apply changes
 * php scripts/backfill_message_charset.php --echomail # echomail only
 * php scripts/backfill_message_charset.php --netmail # netmail only
 * php scripts/backfill_message_charset.php --limit=500
 */

require_once __DIR__ . '/../vendor/autoload.php';
require_once
__DIR__ . '/../src/functions.php';

use
BinktermPHP\Database;
use
BinktermPHP\Binkp\Config\BinkpConfig;

$options = getopt('', ['live', 'limit:', 'echomail', 'netmail']);
$dryRun = !isset($options['live']);
$limit = isset($options['limit']) ? (int)$options['limit'] : null;
$processEcho = isset($options['echomail']) || !isset($options['netmail']);
$processNetmail = isset($options['netmail']) || !isset($options['echomail']);

echo
"=== message_charset Backfill ===\n";
echo
"Mode: " . ($dryRun ? "DRY RUN (pass --live to apply changes)" : "LIVE") . "\n";
if (
$limit) {
    echo
"Limit: $limit rows per table\n";
}
echo
"\n";

$db = Database::getInstance()->getPdo();

/**
 * Extract the raw charset token from the CHRS kludge in kludge_lines.
 *
 * CHRS format: \x01CHRS: <charset> [<level>]
 *
 * @param string $kludgeLines
 * @return string|null Raw charset token (e.g. "IBMPC", "CP866"), or null if absent.
 */
function extractChrsCharset(string $kludgeLines): ?string
{
    foreach (
explode("\n", $kludgeLines) as $line) {
       
$line = trim($line);
        if (
preg_match('/^\x01CHRS:\s*([A-Za-z0-9_\-]+)/i', $line, $m)) {
            return
$m[1];
        }
    }
    return
null;
}

/**
 * Process one table (echomail or netmail) and return counts.
 *
 * @param \PDO $db
 * @param string $table 'echomail' or 'netmail'
 * @param int|null $limit
 * @param bool $dryRun
 * @return array{found: int, updated: int, skipped: int}
 */
function processTable(\PDO $db, string $table, ?int $limit, bool $dryRun): array
{
   
$sql = "SELECT id, kludge_lines FROM {$table}
            WHERE message_charset IS NULL
              AND kludge_lines IS NOT NULL"
;
    if (
$limit) {
       
$sql .= " LIMIT " . (int)$limit;
    }

   
$rows = $db->query($sql)->fetchAll(\PDO::FETCH_ASSOC);
   
$found = count($rows);
   
$updated = 0;
   
$skipped = 0;

    echo
"Processing {$table}...\n";
    echo
str_repeat('-', 60) . "\n";
    echo
"Found {$found} rows with null message_charset\n\n";

   
$updateStmt = $dryRun ? null : $db->prepare(
       
"UPDATE {$table} SET message_charset = ? WHERE id = ?"
   
);

    foreach (
$rows as $row) {
       
$raw = extractChrsCharset($row['kludge_lines']);
        if (
$raw === null) {
           
$skipped++;
            continue;
        }

       
$charset = BinkpConfig::normalizeCharset($raw);

        if (
$dryRun) {
            echo
" [DRY RUN] id={$row['id']} CHRS raw={$raw} -> message_charset={$charset}\n";
        } else {
           
$updateStmt->execute([$charset, $row['id']]);
        }
       
$updated++;

        if (
$updated % 500 === 0) {
            echo
" {$updated} rows processed...\n";
        }
    }

    echo
"\n{$table} results:\n";
    echo
" Updated: {$updated}\n";
    echo
" No CHRS kludge: {$skipped}\n\n";

    return [
'found' => $found, 'updated' => $updated, 'skipped' => $skipped];
}

$totals = ['found' => 0, 'updated' => 0, 'skipped' => 0];

if (
$processEcho) {
   
$r = processTable($db, 'echomail', $limit, $dryRun);
    foreach (
$totals as $k => $_) {
       
$totals[$k] += $r[$k];
    }
}

if (
$processNetmail) {
   
$r = processTable($db, 'netmail', $limit, $dryRun);
    foreach (
$totals as $k => $_) {
       
$totals[$k] += $r[$k];
    }
}

echo
"=== Totals ===\n";
echo
" Rows found: {$totals['found']}\n";
echo
" Updated: {$totals['updated']}\n";
echo
" No CHRS kludge: {$totals['skipped']}\n";

if (
$dryRun) {
    echo
"\nThis was a dry run. Pass --live to apply changes.\n";
}