option('force'); $dryRun = (bool) $this->option('dry-run'); $stats = [ 'checked' => 0, 'created' => 0, 'skipped' => 0, 'missing' => 0, 'non_image' => 0, ]; $this->info('Processing attachment thumbnails...'); Attachment::query() ->orderBy('id') ->chunkById(200, function ($attachments) use ($thumbnailService, $force, $dryRun, &$stats) { foreach ($attachments as $attachment) { $stats['checked']++; $mime = $attachment->mime_type ?? ''; if (!str_starts_with($mime, 'image/')) { $stats['non_image']++; continue; } $disk = Storage::disk($attachment->disk); if (!$disk->exists($attachment->path)) { $stats['missing']++; continue; } $needsThumbnail = $force || !$attachment->thumbnail_path || !$disk->exists($attachment->thumbnail_path); if (!$needsThumbnail) { $stats['skipped']++; continue; } if ($dryRun) { $stats['created']++; continue; } if ($force && $attachment->thumbnail_path && $disk->exists($attachment->thumbnail_path)) { $disk->delete($attachment->thumbnail_path); } $payload = $thumbnailService->createForAttachment($attachment, $force); if (!$payload) { $stats['skipped']++; continue; } $attachment->thumbnail_path = $payload['path'] ?? null; $attachment->thumbnail_mime_type = $payload['mime'] ?? null; $attachment->thumbnail_size_bytes = $payload['size'] ?? null; $attachment->save(); $stats['created']++; } }); $this->info(sprintf( 'Checked: %d | Created: %d | Skipped: %d | Missing: %d | Non-image: %d', $stats['checked'], $stats['created'], $stats['skipped'], $stats['missing'], $stats['non_image'] )); return self::SUCCESS; } }