path(''); if (! is_dir($path)) { @mkdir($path, 0755, true); } /** @var array{total_bytes: int, free_bytes: int, used_bytes: int, used_percent: float, free_percent: float, total_human: string, free_human: string, used_human: string}|null */ return Cache::remember( 'disk-space:'.md5($path), now()->addSeconds(30), fn () => $this->measure($path), ); } /** * @return array{ * total_bytes: int, * free_bytes: int, * used_bytes: int, * used_percent: float, * free_percent: float, * total_human: string, * free_human: string, * used_human: string * }|null */ private function measure(string $path): ?array { $total = @disk_total_space($path); $free = @disk_free_space($path); if ($total === false || $free === false || $total <= 0) { return null; } $totalBytes = (int) $total; $freeBytes = (int) max(0, $free); $usedBytes = (int) max(0, $totalBytes - $freeBytes); $usedPercent = round(($usedBytes / $totalBytes) * 100, 1); $freePercent = round(($freeBytes / $totalBytes) * 100, 1); return [ 'total_bytes' => $totalBytes, 'free_bytes' => $freeBytes, 'used_bytes' => $usedBytes, 'used_percent' => $usedPercent, 'free_percent' => $freePercent, 'total_human' => $this->formatBytes($totalBytes), 'free_human' => $this->formatBytes($freeBytes), 'used_human' => $this->formatBytes($usedBytes), ]; } /** * Human-readable byte size without requiring the intl extension. */ private function formatBytes(int $bytes): string { $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; $value = (float) max(0, $bytes); $unit = 0; while ($value >= 1024 && $unit < count($units) - 1) { $value /= 1024; $unit++; } $precision = $unit === 0 ? 0 : 1; return number_format($value, $precision).' '.$units[$unit]; } }