setDescription("Cleanup pending photo uploads older than specified time")
->addOption(
"max-age",
"a",
InputOption::VALUE_OPTIONAL,
"Maximum age in hours (default: 24)",
24
)
->addOption(
"dry-run",
"d",
InputOption::VALUE_NONE,
"Show what would be deleted without actually deleting"
);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$maxAge = (int) $input->getOption("max-age");
$dryRun = $input->getOption("dry-run");
$photoFolder = __DIR__ . "/../tmp/api-storage/photos";
if (!is_dir($photoFolder)) {
$output->writeln("Photo upload directory not found: {$photoFolder}");
return Command::FAILURE;
}
$output->writeln("Scanning for pending uploads older than {$maxAge} hours...");
$cutoffTime = time() - ($maxAge * 3600);
$deletedCount = 0;
$totalSize = 0;
$files = glob($photoFolder . "/*_*.oct");
foreach ($files as $file) {
$fileTime = filemtime($file);
if ($fileTime < $cutoffTime) {
$fileSize = filesize($file);
$totalSize += $fileSize;
if ($dryRun) {
$age = round((time() - $fileTime) / 3600, 1);
$output->writeln("Would delete: " . basename($file) . " (age: {$age}h, size: " . $this->formatBytes($fileSize) . ")");
} else {
if (unlink($file)) {
$deletedCount++;
$output->writeln("Deleted: " . basename($file) . "");
} else {
$output->writeln("Failed to delete: " . basename($file) . "");
}
}
}
}
if ($dryRun) {
$output->writeln("Dry run completed. Would delete {$deletedCount} files (" . $this->formatBytes($totalSize) . ")");
} else {
$output->writeln("Cleanup completed. Deleted {$deletedCount} files (" . $this->formatBytes($totalSize) . ")");
}
return Command::SUCCESS;
}
private function formatBytes(int $bytes): string
{
$units = ['B', 'KB', 'MB', 'GB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, 2) . ' ' . $units[$pow];
}
}