You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
57 lines
2.1 KiB
57 lines
2.1 KiB
<?php
|
|
|
|
namespace App\Domains\System\Actions\Files;
|
|
|
|
use App\Domains\System\Enums\SystemSettingKey;
|
|
use App\Domains\System\Models\File;
|
|
use App\Domains\System\Queries\GetSystemSettings;
|
|
use App\UI\Enums\InputType;
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
class PruneOrphanedFiles
|
|
{
|
|
public function __construct(protected GetSystemSettings $settingQuery) {}
|
|
|
|
public function execute(string $disk = 'public', string $directory = '/'): array
|
|
{
|
|
$stats = ['db_orphans_removed' => 0, 'disk_orphans_removed' => 0];
|
|
|
|
// --- SWEEP 1: Clean up orphaned Database Records ---
|
|
// Find files where the parent model (fileable) has disappeared
|
|
$orphanedRecords = File::whereDoesntHaveMorph('fileable', '*')->get();
|
|
|
|
foreach ($orphanedRecords as $record) {
|
|
// Because we set up the self-cleaning booted() method earlier,
|
|
// calling delete() here will automatically remove the physical file too!
|
|
$record->delete();
|
|
$stats['db_orphans_removed']++;
|
|
}
|
|
|
|
// --- SWEEP 2: Clean up stranded Physical Files ---
|
|
// Get all files physically sitting on the disk in the target directory
|
|
$physicalFiles = Storage::disk($disk)->allFiles($directory);
|
|
|
|
// Get all file paths currently tracked in the database
|
|
$trackedFiles = File::pluck('path')->toArray();
|
|
|
|
$settingFiles = collect(SystemSettingKey::cases())
|
|
->filter(fn ($key) => $key->inputType() === InputType::FILE)
|
|
->map(fn ($key) => $this->settingQuery->get($key))
|
|
->filter()
|
|
->toArray();
|
|
|
|
$trackedFiles = array_merge($trackedFiles, $settingFiles);
|
|
$trackedFiles[] = 'images/logo.svg';
|
|
|
|
// Compare the two arrays to find files on disk that the DB knows nothing about
|
|
$strandedFiles = array_diff($physicalFiles, $trackedFiles);
|
|
$strandedFiles = array_filter($strandedFiles, fn ($file) => basename($file) !== '.gitignore');
|
|
|
|
if (! empty($strandedFiles)) {
|
|
Storage::disk($disk)->delete($strandedFiles);
|
|
$stats['disk_orphans_removed'] = count($strandedFiles);
|
|
}
|
|
|
|
return $stats;
|
|
}
|
|
}
|
|
|