dstpabuaran.com/app/Jobs/CleanupOrphanedMediaJob.php

97 lines
2.5 KiB
PHP

<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class CleanupOrphanedMediaJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 3;
public int $chunkSize = 100;
public function handle(): void
{
$orphanedMedia = $this->getOrphanedMedia();
if ($orphanedMedia->isEmpty()) {
Log::info('CleanupOrphanedMediaJob: Tidak ada media orphaned.');
return;
}
$totalDeleted = 0;
$orphanedMedia->each(function (Media $media) use (&$totalDeleted) {
$this->deleteMedia($media);
$totalDeleted++;
});
Log::info("CleanupOrphanedMediaJob: Berhasil hapus {$totalDeleted} media orphaned.");
}
private function getOrphanedMedia()
{
$allMedia = Media::select(['id', 'model_type', 'model_id', 'file_name', 'custom_properties', 'disk'])
->get()
->groupBy(fn (Media $m) => $m->model_type.'|'.$m->model_id);
$orphanedIds = [];
foreach ($allMedia as $key => $mediaItems) {
[$modelType, $modelId] = explode('|', $key);
if ($this->isOrphaned($modelType, (int) $modelId)) {
foreach ($mediaItems as $media) {
$orphanedIds[] = $media->id;
}
}
}
if (empty($orphanedIds)) {
return collect();
}
return Media::whereIn('id', $orphanedIds)->get();
}
private function isOrphaned(string $modelType, int $modelId): bool
{
if (! class_exists($modelType)) {
return true;
}
$model = $modelType::withTrashed()->find($modelId);
if (! $model) {
return true;
}
if (method_exists($model, 'trashed') && $model->trashed()) {
return $model->deleted_at->lt(now()->subMonth());
}
return false;
}
private function deleteMedia(Media $media): void
{
$s3Key = $media->getCustomProperty('s3_key');
if ($s3Key && Storage::disk($media->disk)->exists($s3Key)) {
Storage::disk($media->disk)->delete($s3Key);
}
$media->forceDelete();
}
}