option('site'); $this->info(''); $this->info('File Storage System Statistics'); $this->info('=============================='); $this->info(''); // Basic counts $storage_count = File_Storage_Model::count(); $attachment_query = File_Attachment_Model::query(); if ($site_id) { $attachment_query->where('site_id', $site_id); } $attachment_count = $attachment_query->count(); // Deduplication ratio $dedup_ratio = $storage_count > 0 ? round($attachment_count / $storage_count, 2) : 0; $this->info('Overview:'); $this->info(" Physical Files: {$storage_count}"); $this->info(" Total Attachments: {$attachment_count}"); $this->info(" Deduplication: {$dedup_ratio}x (avg attachments per file)"); $this->info(''); // Storage size stats $total_size = File_Storage_Model::sum('size'); $avg_size = $storage_count > 0 ? round($total_size / $storage_count) : 0; $this->info('Storage Usage:'); $this->info(" Total Disk Space: " . $this->format_bytes($total_size)); $this->info(" Average File Size: " . $this->format_bytes($avg_size)); $this->info(''); // Files by type $type_query = File_Attachment_Model::select('file_type_id', DB::raw('COUNT(*) as count')); if ($site_id) { $type_query->where('site_id', $site_id); } $types_breakdown = $type_query->groupBy('file_type_id')->get(); if ($types_breakdown->isNotEmpty()) { $this->info('Files by Type:'); $type_names = [ 1 => 'Image', 2 => 'Animated Image', 3 => 'Video', 4 => 'Archive', 5 => 'Text', 6 => 'Document', 7 => 'Other', ]; foreach ($types_breakdown as $type) { $name = $type_names[$type->file_type_id] ?? 'Unknown'; $percentage = $attachment_count > 0 ? round(($type->count / $attachment_count) * 100, 1) : 0; $this->info(sprintf(" %-16s %6d (%5.1f%%)", $name . ':', $type->count, $percentage)); } $this->info(''); } // Orphaned storage (no attachments) $orphaned_storage = DB::table('_file_storage') ->leftJoin('file_attachments', 'file_storage.id', '=', 'file_attachments.file_storage_id') ->whereNull('file_attachments.id') ->count(); // Orphaned attachments (no fileable) $orphaned_query = File_Attachment_Model::whereNull('fileable_type') ->whereNull('fileable_id'); if ($site_id) { $orphaned_query->where('site_id', $site_id); } $orphaned_attachments = $orphaned_query->count(); // Old orphaned attachments (>24 hours) $old_orphaned_query = File_Attachment_Model::whereNull('fileable_type') ->whereNull('fileable_id') ->where('created_at', '<', now()->subHours(24)); if ($site_id) { $old_orphaned_query->where('site_id', $site_id); } $old_orphaned_attachments = $old_orphaned_query->count(); $this->info('Orphaned Files:'); $this->info(" Orphaned Storage: {$orphaned_storage}"); $this->info(" Orphaned Attachments: {$orphaned_attachments}"); $this->info(" Old Orphans (>24h): {$old_orphaned_attachments}"); if ($old_orphaned_attachments > 0) { $this->warn(" Warning: {$old_orphaned_attachments} attachments eligible for cleanup"); } $this->info(''); if ($site_id) { $this->info("(Statistics filtered for site ID: {$site_id})"); $this->info(''); } return 0; } /** * Format bytes to human-readable size */ protected function format_bytes($bytes) { $units = ['B', 'KB', 'MB', 'GB', 'TB']; for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) { $bytes /= 1024; } return round($bytes, 2) . ' ' . $units[$i]; } }