Files
usher-manage-stack/app/Models/DocumentVersion.php
2025-11-20 23:21:05 +08:00

168 lines
4.0 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class DocumentVersion extends Model
{
use HasFactory;
protected $fillable = [
'document_id',
'version_number',
'version_notes',
'is_current',
'file_path',
'original_filename',
'mime_type',
'file_size',
'file_hash',
'uploaded_by_user_id',
'uploaded_at',
];
protected $casts = [
'is_current' => 'boolean',
'uploaded_at' => 'datetime',
];
// Versions are immutable - disable updating
protected static function booted()
{
static::updating(function ($version) {
// Only allow updating is_current flag
$dirty = $version->getDirty();
if (count($dirty) > 1 || !isset($dirty['is_current'])) {
throw new \Exception('Document versions are immutable and cannot be modified');
}
});
}
// ==================== Relationships ====================
/**
* Get the document this version belongs to
*/
public function document()
{
return $this->belongsTo(Document::class);
}
/**
* Get the user who uploaded this version
*/
public function uploadedBy()
{
return $this->belongsTo(User::class, 'uploaded_by_user_id');
}
// ==================== File Methods ====================
/**
* Get the full file path
*/
public function getFullPath(): string
{
return storage_path('app/' . $this->file_path);
}
/**
* Check if file exists
*/
public function fileExists(): bool
{
return Storage::exists($this->file_path);
}
/**
* Get file download URL
*/
public function getDownloadUrl(): string
{
return route('admin.documents.download-version', [
'document' => $this->document_id,
'version' => $this->id,
]);
}
/**
* Verify file integrity
*/
public function verifyIntegrity(): bool
{
if (!$this->fileExists()) {
return false;
}
$currentHash = hash_file('sha256', $this->getFullPath());
return $currentHash === $this->file_hash;
}
// ==================== Helper Methods ====================
/**
* Get human-readable file size
*/
public function getFileSizeHuman(): string
{
$bytes = $this->file_size;
$units = ['B', 'KB', 'MB', 'GB'];
for ($i = 0; $bytes > 1024; $i++) {
$bytes /= 1024;
}
return round($bytes, 2) . ' ' . $units[$i];
}
/**
* Get file extension
*/
public function getFileExtension(): string
{
return pathinfo($this->original_filename, PATHINFO_EXTENSION);
}
/**
* Get file icon based on mime type
*/
public function getFileIcon(): string
{
return match(true) {
str_contains($this->mime_type, 'pdf') => '📄',
str_contains($this->mime_type, 'word') || str_contains($this->mime_type, 'document') => '📝',
str_contains($this->mime_type, 'sheet') || str_contains($this->mime_type, 'excel') => '📊',
str_contains($this->mime_type, 'image') => '🖼️',
str_contains($this->mime_type, 'zip') || str_contains($this->mime_type, 'compressed') => '🗜️',
default => '📎',
};
}
/**
* Check if version is current
*/
public function isCurrent(): bool
{
return $this->is_current;
}
/**
* Get version badge class for UI
*/
public function getBadgeClass(): string
{
return $this->is_current ? 'bg-green-100 text-green-800' : 'bg-gray-100 text-gray-800';
}
/**
* Get version badge text
*/
public function getBadgeText(): string
{
return $this->is_current ? '當前版本' : '歷史版本';
}
}