-
Please examine code for your approval and correction and yes, the above method is included: Final Code from my side... The minute I have the replica setup, I will start testing and give feedback to the community how things go
<?php
/**
* UNA Timeline Cleanup Script - Safe Version
* Deletes old timeline posts and their associated media files properly
*
* IMPORTANT: Test with $dryRun = true first!
*/
// Bootstrap UNA
require_once __DIR__ . '/inc/header.inc.php';
// ===== CONFIGURATION =====
$daysOld = 60; // Delete posts older than this many days
$dryRun = true; // SET TO FALSE when ready to actually delete
$batch = 200; // Process this many posts per run
$lockFile = __DIR__ . '/timeline_cleanup.lock';
$logFile = __DIR__ . '/timeline_cleanup.log';
// ===== LOCK CHECK (prevent concurrent runs) =====
if (file_exists($lockFile)) {
$lockAge = time() - filemtime($lockFile);
if ($lockAge < 3600) { // 1 hour lock timeout
die("Script is already running (lock file exists)\n");
}
unlink($lockFile); // Remove stale lock
}
file_put_contents($lockFile, getmypid() . "\n" . date('Y-m-d H:i:s'));
// ===== SETUP =====
$cutoff = time() - (86400 * $daysOld);
$db = BxDolDb::getInstance();
// Start logging
$logMsg = "\n" . str_repeat('=', 60) . "\n";
$logMsg .= "Timeline Cleanup Run: " . date('Y-m-d H:i:s') . "\n";
$logMsg .= "Mode: " . ($dryRun ? "DRY RUN (no deletions)" : "LIVE (deleting)") . "\n";
$logMsg .= "Cutoff date: " . date('Y-m-d H:i:s', $cutoff) . "\n";
$logMsg .= str_repeat('=', 60) . "\n";
file_put_contents($logFile, $logMsg, FILE_APPEND);
// ===== GET OLD EVENTS =====
try {
$eventIds = $db->getColumn("
SELECT `id`
FROM `bx_timeline_events`
WHERE `type` = 'post'
AND `date` < ?
ORDER BY `date` ASC
LIMIT ?
", [$cutoff, $batch]);
} catch (Exception $e) {
$error = "ERROR: Database query failed: " . $e->getMessage() . "\n";
file_put_contents($logFile, $error, FILE_APPEND);
unlink($lockFile);
die($error);
}
if (empty($eventIds)) {
$msg = "No old events found to process.\n";
echo $msg;
file_put_contents($logFile, $msg, FILE_APPEND);
unlink($lockFile);
exit(0);
}
echo "Found " . count($eventIds) . " events to process\n";
file_put_contents($logFile, "Found " . count($eventIds) . " events\n", FILE_APPEND);
// ===== LOAD TIMELINE MODULE =====
$timeline = BxDolModule::getInstance('bx_timeline');
if (!$timeline) {
$error = "FATAL ERROR: Timeline module not found!\n";
file_put_contents($logFile, $error, FILE_APPEND);
unlink($lockFile);
die($error);
}
// ===== PROCESS DELETIONS =====
$deleted = 0;
$failed = 0;
foreach ($eventIds as $eventId) {
$eventId = (int)$eventId;
// Get event details for logging
$aEvent = $db->getRow("SELECT * FROM `bx_timeline_events` WHERE `id` = ?", [$eventId]);
if (empty($aEvent)) {
$msg = "Event $eventId not found (already deleted?)\n";
echo $msg;
file_put_contents($logFile, $msg, FILE_APPEND);
continue;
}
if ($dryRun) {
$msg = "[DRY RUN] Would delete event: $eventId (owner: {$aEvent['owner_id']}, date: " .
date('Y-m-d', $aEvent['date']) . ")\n";
echo $msg;
file_put_contents($logFile, $msg, FILE_APPEND);
$deleted++;
continue;
}
// ===== ACTUAL DELETION (uses UNA's native method) =====
try {
// This is the safe method that handles all cleanup:
// - Deletes from bx_timeline_events
// - Removes associated media files from storage
// - Cleans up comments, reactions, votes, reports
// - Triggers all necessary hooks
$result = $timeline->deleteEvent($aEvent);
if ($result) {
$deleted++;
$msg = "✓ Deleted event: $eventId (owner: {$aEvent['owner_id']})\n";
echo $msg;
file_put_contents($logFile, $msg, FILE_APPEND);
} else {
$failed++;
$msg = "✗ Failed to delete event: $eventId\n";
echo $msg;
file_put_contents($logFile, $msg, FILE_APPEND);
}
} catch (Exception $e) {
$failed++;
$msg = "✗ Exception deleting event $eventId: " . $e->getMessage() . "\n";
echo $msg;
file_put_contents($logFile, $msg, FILE_APPEND);
}
// Small delay to prevent overwhelming the system
usleep(50000); // 0.05 seconds
}
// ===== SUMMARY =====
$summary = "\n" . str_repeat('-', 60) . "\n";
$summary .= "Summary:\n";
$summary .= " Total found: " . count($eventIds) . "\n";
$summary .= " Successfully deleted: $deleted\n";
$summary .= " Failed: $failed\n";
$summary .= str_repeat('-', 60) . "\n\n";
echo $summary;
file_put_contents($logFile, $summary, FILE_APPEND);
// ===== CLEANUP =====
unlink($lockFile);
// ===== NEXT STEPS MESSAGE =====
if ($dryRun) {
echo "\n";
echo "DRY RUN COMPLETE - No actual deletions performed.\n";
echo "Review the log file: $logFile\n";
echo "\n";
echo "To perform actual deletions:\n";
echo "1. Check the log to verify correct events are targeted\n";
echo "2. Set \$dryRun = false in the script\n";
echo "3. Start with a small batch (e.g., \$batch = 10)\n";
echo "4. Monitor disk usage before/after\n";
echo "5. Gradually increase batch size if successful\n";
echo "\n";
} else {
echo "\nTo continue cleanup, run this script again.\n";
echo "It will process the next $batch events.\n";
}