hasMany(File_Model::class, 'file_hash_id'); } /** * Get the storage path for this file * Based on the hash for efficient file system distribution * * @return string */ public function get_storage_path() { // Split hash into subdirectories for better file system performance // e.g., hash "abc123..." becomes "storage/files/ab/c1/abc123..." $hash = $this->hash; $dir1 = substr($hash, 0, 2); $dir2 = substr($hash, 2, 2); return "storage/files/{$dir1}/{$dir2}/{$hash}"; } /** * Get the full file system path * * @return string */ public function get_full_path() { return storage_path($this->get_storage_path()); } /** * Check if the physical file exists on disk * * @return bool */ public function file_exists() { return file_exists($this->get_full_path()); } /** * Get human-readable file size * * @return string */ public function get_human_size() { $bytes = $this->size; $units = ['B', 'KB', 'MB', 'GB', 'TB']; for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) { $bytes /= 1024; } return round($bytes, 2) . ' ' . $units[$i]; } /** * Find or create a file hash record * * @param string $hash * @param string $mime_type * @param int $size * @return static */ public static function find_or_create($hash, $mime_type, $size) { $file_hash = static::where('hash', $hash)->first(); if (!$file_hash) { $file_hash = new static(); $file_hash->hash = $hash; $file_hash->mime_type = $mime_type; $file_hash->size = $size; $file_hash->save(); } return $file_hash; } /** * Calculate hash for file content * * @param string $content * @return string */ public static function calculate_hash($content) { return hash('sha256', $content); } /** * Calculate hash for a file path * * @param string $file_path * @return string|false */ public static function calculate_file_hash($file_path) { if (!file_exists($file_path)) { return false; } return hash_file('sha256', $file_path); } }