2026-04-03 00:29:05 +03:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
|
|
|
|
|
|
use App\Models\Job;
|
|
|
|
|
use Illuminate\Console\Attributes\Description;
|
|
|
|
|
use Illuminate\Console\Attributes\Signature;
|
|
|
|
|
use Illuminate\Console\Command;
|
|
|
|
|
|
|
|
|
|
#[Signature('jobs:clean {--days=30} {--force}')]
|
|
|
|
|
#[Description('Remove expired and old job listings from the database')]
|
|
|
|
|
class CleanJobs extends Command
|
|
|
|
|
{
|
2026-05-01 23:33:15 +03:00
|
|
|
protected $signature = 'jobs:clean {--days=30} {--force}';
|
|
|
|
|
protected $description = 'Remove expired and old job listings from the database';
|
|
|
|
|
|
2026-04-03 00:29:05 +03:00
|
|
|
/**
|
|
|
|
|
* Execute the console command.
|
|
|
|
|
*/
|
|
|
|
|
public function handle(): int
|
|
|
|
|
{
|
|
|
|
|
$days = (int) $this->option('days');
|
|
|
|
|
$force = $this->option('force');
|
|
|
|
|
|
|
|
|
|
$this->info("Cleaning job listings...");
|
|
|
|
|
$this->newLine();
|
|
|
|
|
|
|
|
|
|
// Remove expired jobs
|
|
|
|
|
$expiredCount = $this->removeExpiredJobs($force);
|
|
|
|
|
|
|
|
|
|
// Remove old jobs (not posted in the last X days)
|
|
|
|
|
$oldCount = $this->removeOldJobs($days, $force);
|
|
|
|
|
|
|
|
|
|
// Clean up soft-deleted jobs
|
|
|
|
|
$trashedCount = $this->cleanTrashedJobs($force);
|
|
|
|
|
|
|
|
|
|
$this->newLine();
|
|
|
|
|
$this->info("Cleanup Summary:");
|
|
|
|
|
$this->line(" • Expired jobs removed: {$expiredCount}");
|
|
|
|
|
$this->line(" • Old jobs removed (>{$days} days): {$oldCount}");
|
|
|
|
|
$this->line(" • Trashed jobs cleaned: {$trashedCount}");
|
|
|
|
|
$this->line(" • Total removed: " . ($expiredCount + $oldCount + $trashedCount));
|
|
|
|
|
|
|
|
|
|
return self::SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function removeExpiredJobs(bool $force): int
|
|
|
|
|
{
|
|
|
|
|
$query = Job::whereNotNull('expires_at')
|
|
|
|
|
->where('expires_at', '<', now());
|
|
|
|
|
|
|
|
|
|
$count = $query->count();
|
|
|
|
|
|
|
|
|
|
if ($count === 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$force) {
|
|
|
|
|
$this->line("Found {$count} expired jobs (soft deleting)...");
|
|
|
|
|
$query->delete(); // Soft delete
|
|
|
|
|
} else {
|
|
|
|
|
$this->line("Found {$count} expired jobs (force deleting)...");
|
|
|
|
|
$query->forceDelete(); // Permanent delete
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function removeOldJobs(int $days, bool $force): int
|
|
|
|
|
{
|
|
|
|
|
$cutoffDate = now()->subDays($days);
|
|
|
|
|
|
|
|
|
|
$query = Job::where(function ($q) use ($cutoffDate) {
|
|
|
|
|
$q->where('posted_at', '<', $cutoffDate)
|
|
|
|
|
->orWhere(function ($q2) use ($cutoffDate) {
|
|
|
|
|
$q2->whereNull('posted_at')
|
|
|
|
|
->where('created_at', '<', $cutoffDate);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$count = $query->count();
|
|
|
|
|
|
|
|
|
|
if ($count === 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$force) {
|
|
|
|
|
$this->line("Found {$count} old jobs (soft deleting)...");
|
|
|
|
|
$query->delete(); // Soft delete
|
|
|
|
|
} else {
|
|
|
|
|
$this->line("Found {$count} old jobs (force deleting)...");
|
|
|
|
|
$query->forceDelete(); // Permanent delete
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function cleanTrashedJobs(bool $force): int
|
|
|
|
|
{
|
|
|
|
|
if (!$force) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Permanently delete jobs that have been soft-deleted for more than 30 days
|
|
|
|
|
$query = Job::onlyTrashed()
|
|
|
|
|
->where('deleted_at', '<', now()->subDays(30));
|
|
|
|
|
|
|
|
|
|
$count = $query->count();
|
|
|
|
|
|
|
|
|
|
if ($count > 0) {
|
|
|
|
|
$this->line("Found {$count} trashed jobs older than 30 days (permanently deleting)...");
|
|
|
|
|
$query->forceDelete();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $count;
|
|
|
|
|
}
|
|
|
|
|
}
|