php/src/Core/Console/Commands/PruneEmailShieldStatsCommand.php
Snider 208cb93c95
All checks were successful
CI / PHP 8.3 (pull_request) Successful in 2m32s
CI / PHP 8.4 (pull_request) Successful in 2m17s
fix(dx): code style fixes, strict_types, and test repair
- Remove non-existent src/Core/Service/ from CLAUDE.md L1 packages list
- Fix LifecycleEventsTest: remove dependency on McpToolHandler interface
  (lives in core-mcp, not needed since McpToolsRegistering stores class
  name strings)
- Run Laravel Pint to fix PSR-12 violations across all source and test files
- Add missing declare(strict_types=1) to 18 PHP files (tests, seeders,
  Layout.php, GenerateServiceOgImages.php)

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-17 09:03:50 +00:00

148 lines
4.5 KiB
PHP

<?php
/*
* Core PHP Framework
*
* Licensed under the European Union Public Licence (EUPL) v1.2.
* See LICENSE file for details.
*/
declare(strict_types=1);
namespace Core\Console\Commands;
use Core\Mail\EmailShieldStat;
use Illuminate\Console\Command;
use Symfony\Component\Console\Completion\CompletionInput;
use Symfony\Component\Console\Completion\CompletionSuggestions;
/**
* Prune old Email Shield statistics records.
*
* Removes records older than the specified retention period to prevent
* unbounded table growth. Should be scheduled to run daily.
*
* Usage:
* php artisan email-shield:prune
* php artisan email-shield:prune --days=30
*
* Scheduling (in app/Console/Kernel.php):
* $schedule->command('email-shield:prune')->daily();
*/
class PruneEmailShieldStatsCommand extends Command
{
/**
* The name and signature of the console command.
*/
protected $signature = 'email-shield:prune
{--days= : Number of days to retain (default: from config or 90)}
{--dry-run : Show what would be deleted without actually deleting}';
/**
* The console command description.
*/
protected $description = 'Prune old Email Shield statistics records';
/**
* Execute the console command.
*/
public function handle(): int
{
$days = $this->getRetentionDays();
$dryRun = $this->option('dry-run');
$this->newLine();
$this->components->info('Email Shield Stats Cleanup');
$this->newLine();
// Get count of records that would be deleted
$cutoffDate = now()->subDays($days)->format('Y-m-d');
$recordsToDelete = EmailShieldStat::query()
->where('date', '<', $cutoffDate)
->count();
// Show current state table
$this->components->twoColumnDetail('<fg=gray;options=bold>Configuration</>', '');
$this->components->twoColumnDetail('Retention period', "<fg=cyan>{$days} days</>");
$this->components->twoColumnDetail('Cutoff date', "<fg=cyan>{$cutoffDate}</>");
$this->components->twoColumnDetail('Records to delete', $recordsToDelete > 0
? "<fg=yellow>{$recordsToDelete}</>"
: '<fg=green>0</>');
$this->newLine();
if ($recordsToDelete === 0) {
$this->components->info('No records older than the retention period found.');
$this->newLine();
return self::SUCCESS;
}
if ($dryRun) {
$this->components->warn('Dry run mode - no records were deleted.');
$this->newLine();
return self::SUCCESS;
}
// Show progress for deletion
$this->components->task(
"Deleting {$recordsToDelete} old records",
function () use ($days) {
EmailShieldStat::pruneOldRecords($days);
return true;
}
);
$this->newLine();
$this->components->info("Successfully deleted {$recordsToDelete} records older than {$days} days.");
$this->newLine();
// Show remaining stats
$remaining = EmailShieldStat::getRecordCount();
$oldest = EmailShieldStat::getOldestRecordDate();
$this->components->twoColumnDetail('<fg=gray;options=bold>Current State</>', '');
$this->components->twoColumnDetail('Remaining records', "<fg=cyan>{$remaining}</>");
if ($oldest) {
$this->components->twoColumnDetail('Oldest record', "<fg=cyan>{$oldest->format('Y-m-d')}</>");
}
$this->newLine();
return self::SUCCESS;
}
/**
* Get the retention period in days from option, config, or default.
*/
protected function getRetentionDays(): int
{
// First check command option
$days = $this->option('days');
if ($days !== null) {
return (int) $days;
}
// Then check config
$configDays = config('core.email_shield.retention_days');
if ($configDays !== null) {
return (int) $configDays;
}
// Default to 90 days
return 90;
}
/**
* Get shell completion suggestions for options.
*/
public function complete(
CompletionInput $input,
CompletionSuggestions $suggestions
): void {
if ($input->mustSuggestOptionValuesFor('days')) {
// Suggest common retention periods
$suggestions->suggestValues(['7', '14', '30', '60', '90', '180', '365']);
}
}
}