PHP Classes

File: scripts/fix_date_received.php

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   scripts/fix_date_received.php   Download  
File: scripts/fix_date_received.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: 6 days ago
Size: 7,419 bytes
 

Contents

Class file image Download
#!/usr/bin/env php
<?php
/**
 * fix_date_received.php
 *
 * Sets date_received = date_written for echomail in one or more echo areas.
 * Useful after a %RESCAN import where all messages land with the same
 * date_received (import time) instead of their original send date.
 *
 * Only rows where date_written is non-NULL and not in the future are updated.
 * Rows where date_written already equals date_received are skipped.
 *
 * Usage:
 * php scripts/fix_date_received.php <echoarea_id> [echoarea_id ...]
 * php scripts/fix_date_received.php --tag <tag> [tag ...]
 * php scripts/fix_date_received.php --domain <domain> [domain ...]
 * php scripts/fix_date_received.php --tag <tag> --domain <domain>
 * php scripts/fix_date_received.php --all
 *
 * --tag and --domain may be combined: only areas matching both filters are
 * updated. --domain alone applies to all areas in that domain. --tag alone
 * applies to every area with that tag across all domains.
 *
 * Options:
 * --dry-run Show what would be updated without making changes
 * --all Apply to every echo area
 * --tag <tag> Filter by tag name (repeatable)
 * --domain <name> Filter by domain (repeatable)
 */

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

use
BinktermPHP\Database;

// ?? Argument parsing ??????????????????????????????????????????????????????????

$args = array_slice($argv, 1);
$dryRun = false;
$all = false;
$tags = [];
$domains = [];
$ids = [];
$mode = null; // current collection target: 'tag', 'domain', or null (ids)

foreach ($args as $a) {
    if (
$a === '--dry-run') {
       
$dryRun = true;
       
$mode = null;
    } elseif (
$a === '--all') {
       
$all = true;
       
$mode = null;
    } elseif (
$a === '--tag') {
       
$mode = 'tag';
    } elseif (
$a === '--domain') {
       
$mode = 'domain';
    } elseif (
str_starts_with($a, '--')) {
       
fwrite(STDERR, "Unknown option: $a\n");
        exit(
1);
    } else {
        if (
$mode === 'tag') {
           
$tags[] = $a;
        } elseif (
$mode === 'domain') {
           
$domains[] = $a;
        } else {
           
$ids[] = $a;
        }
    }
}

$hasFilter = $all || !empty($ids) || !empty($tags) || !empty($domains);

if (!
$hasFilter) {
   
fwrite(STDERR, "Usage:\n");
   
fwrite(STDERR, " php scripts/fix_date_received.php <echoarea_id> [id ...]\n");
   
fwrite(STDERR, " php scripts/fix_date_received.php --tag <tag> [tag ...]\n");
   
fwrite(STDERR, " php scripts/fix_date_received.php --domain <domain> [domain ...]\n");
   
fwrite(STDERR, " php scripts/fix_date_received.php --tag <tag> --domain <domain>\n");
   
fwrite(STDERR, " php scripts/fix_date_received.php --all\n");
   
fwrite(STDERR, "\nOptions:\n");
   
fwrite(STDERR, " --dry-run Show changes without applying them\n");
   
fwrite(STDERR, " --all Apply to every echo area\n");
   
fwrite(STDERR, " --tag <tag> Filter by tag (repeatable; combinable with --domain)\n");
   
fwrite(STDERR, " --domain <name> Filter by domain (repeatable; combinable with --tag)\n");
    exit(
1);
}

if (!empty(
$ids)) {
    foreach (
$ids as $id) {
        if (!
ctype_digit($id)) {
           
fwrite(STDERR, "Error: '$id' is not a numeric id. Use --tag to match by name.\n");
            exit(
1);
        }
    }
}

// ?? Database ??????????????????????????????????????????????????????????????????

$db = Database::getInstance()->getPdo();
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// ?? Resolve areas ?????????????????????????????????????????????????????????????

$areas = [];

if (
$all) {
   
$stmt = $db->query("SELECT id, tag, domain FROM echoareas ORDER BY domain, tag");
   
$areas = $stmt->fetchAll(PDO::FETCH_ASSOC);
} elseif (!empty(
$ids)) {
   
$ph = implode(',', array_fill(0, count($ids), '?'));
   
$stmt = $db->prepare("SELECT id, tag, domain FROM echoareas WHERE id IN ($ph) ORDER BY id");
   
$stmt->execute($ids);
   
$areas = $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach (
$ids as $id) {
        if (!
in_array((int)$id, array_map('intval', array_column($areas, 'id')))) {
           
fwrite(STDERR, "Warning: echo area id not found: $id\n");
        }
    }
} else {
   
// Tag and/or domain filter ? build WHERE dynamically
   
$conditions = [];
   
$params = [];

    if (!empty(
$tags)) {
       
$ph = implode(',', array_fill(0, count($tags), '?'));
       
$conditions[] = "LOWER(tag) IN ($ph)";
       
$params = array_merge($params, array_map('strtolower', $tags));
    }

    if (!empty(
$domains)) {
       
$ph = implode(',', array_fill(0, count($domains), '?'));
       
$conditions[] = "LOWER(domain) IN ($ph)";
       
$params = array_merge($params, array_map('strtolower', $domains));
    }

   
$where = implode(' AND ', $conditions);
   
$stmt = $db->prepare("SELECT id, tag, domain FROM echoareas WHERE $where ORDER BY domain, tag");
   
$stmt->execute($params);
   
$areas = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (!empty(
$tags)) {
       
$foundTags = array_map('strtolower', array_column($areas, 'tag'));
        foreach (
$tags as $t) {
            if (!
in_array(strtolower($t), $foundTags)) {
               
fwrite(STDERR, "Warning: no areas found for tag: $t\n");
            }
        }
    }
}

if (empty(
$areas)) {
   
fwrite(STDERR, "No matching echo areas found.\n");
    exit(
1);
}

// ?? Process ???????????????????????????????????????????????????????????????????

if ($dryRun) {
    echo
"[DRY RUN] No changes will be written.\n\n";
}

echo
"Processing " . count($areas) . " echo area(s)...\n\n";

$totalUpdated = 0;

foreach (
$areas as $area) {
   
$areaId = (int)$area['id'];
   
$label = $area['tag'] . ($area['domain'] ? '@' . $area['domain'] : '');

   
$countStmt = $db->prepare("
        SELECT COUNT(*) FROM echomail
        WHERE echoarea_id = ?
          AND date_written IS NOT NULL
          AND date_written <= NOW()
          AND date_written IS DISTINCT FROM date_received
    "
);
   
$countStmt->execute([$areaId]);
   
$count = (int)$countStmt->fetchColumn();

    if (
$count === 0) {
        echo
"[$label] No rows to update.\n";
        continue;
    }

    if (
$dryRun) {
        echo
"[$label] Would update $count row(s).\n";
       
$totalUpdated += $count;
        continue;
    }

   
$updateStmt = $db->prepare("
        UPDATE echomail
        SET date_received = date_written
        WHERE echoarea_id = ?
          AND date_written IS NOT NULL
          AND date_written <= NOW()
          AND date_written IS DISTINCT FROM date_received
    "
);
   
$updateStmt->execute([$areaId]);
   
$affected = $updateStmt->rowCount();

    echo
"[$label] Updated $affected row(s).\n";
   
$totalUpdated += $affected;
}

echo
"\nTotal: $totalUpdated row(s) " . ($dryRun ? 'would be ' : '') . "updated.\n";