Initial commit
This commit is contained in:
189
app/Console/Commands/ImportDocuments.php
Normal file
189
app/Console/Commands/ImportDocuments.php
Normal file
@@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\AuditLog;
|
||||
use App\Models\Document;
|
||||
use App\Models\DocumentCategory;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ImportDocuments extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'documents:import
|
||||
{path : Path to directory containing documents and manifest.json}
|
||||
{--user-id=1 : User ID to attribute uploads to}
|
||||
{--dry-run : Preview import without making changes}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Bulk import documents from a directory with manifest.json';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$path = $this->argument('path');
|
||||
$userId = $this->option('user-id');
|
||||
$dryRun = $this->option('dry-run');
|
||||
|
||||
// Validate path
|
||||
if (!File::isDirectory($path)) {
|
||||
$this->error("Directory not found: {$path}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Check for manifest.json
|
||||
$manifestPath = $path . '/manifest.json';
|
||||
if (!File::exists($manifestPath)) {
|
||||
$this->error("manifest.json not found in {$path}");
|
||||
$this->info("Expected format:");
|
||||
$this->line($this->getManifestExample());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Load manifest
|
||||
$manifest = json_decode(File::get($manifestPath), true);
|
||||
if (!$manifest || !isset($manifest['documents'])) {
|
||||
$this->error("Invalid manifest.json format");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Validate user
|
||||
$user = User::find($userId);
|
||||
if (!$user) {
|
||||
$this->error("User not found: {$userId}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->info("Importing documents from: {$path}");
|
||||
$this->info("Attributed to: {$user->name}");
|
||||
if ($dryRun) {
|
||||
$this->warn("DRY RUN - No changes will be made");
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
$successCount = 0;
|
||||
$errorCount = 0;
|
||||
|
||||
foreach ($manifest['documents'] as $item) {
|
||||
try {
|
||||
$this->processDocument($path, $item, $user, $dryRun);
|
||||
$successCount++;
|
||||
} catch (\Exception $e) {
|
||||
$this->error("Error processing {$item['file']}: {$e->getMessage()}");
|
||||
$errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->newLine();
|
||||
$this->info("Import complete!");
|
||||
$this->info("Success: {$successCount}");
|
||||
if ($errorCount > 0) {
|
||||
$this->error("Errors: {$errorCount}");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected function processDocument(string $basePath, array $item, User $user, bool $dryRun): void
|
||||
{
|
||||
$filePath = $basePath . '/' . $item['file'];
|
||||
|
||||
// Validate file exists
|
||||
if (!File::exists($filePath)) {
|
||||
throw new \Exception("File not found: {$filePath}");
|
||||
}
|
||||
|
||||
// Find or create category
|
||||
$category = DocumentCategory::where('slug', $item['category'])->first();
|
||||
if (!$category) {
|
||||
throw new \Exception("Category not found: {$item['category']}");
|
||||
}
|
||||
|
||||
$this->line("Processing: {$item['title']}");
|
||||
$this->line(" Category: {$category->name}");
|
||||
$this->line(" File: {$item['file']}");
|
||||
|
||||
if ($dryRun) {
|
||||
$this->line(" [DRY RUN] Would create document");
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy file to storage
|
||||
$fileInfo = pathinfo($filePath);
|
||||
$storagePath = 'documents/' . uniqid() . '.' . $fileInfo['extension'];
|
||||
Storage::disk('private')->put($storagePath, File::get($filePath));
|
||||
|
||||
// Create document
|
||||
$document = Document::create([
|
||||
'document_category_id' => $category->id,
|
||||
'title' => $item['title'],
|
||||
'document_number' => $item['document_number'] ?? null,
|
||||
'description' => $item['description'] ?? null,
|
||||
'access_level' => $item['access_level'] ?? $category->default_access_level,
|
||||
'status' => 'active',
|
||||
'created_by' => $user->id,
|
||||
'updated_by' => $user->id,
|
||||
]);
|
||||
|
||||
// Add first version
|
||||
$document->addVersion(
|
||||
filePath: $storagePath,
|
||||
originalFilename: $fileInfo['basename'],
|
||||
mimeType: File::mimeType($filePath),
|
||||
fileSize: File::size($filePath),
|
||||
uploadedBy: $user,
|
||||
versionNotes: $item['version_notes'] ?? 'Initial import'
|
||||
);
|
||||
|
||||
AuditLog::create([
|
||||
'user_id' => $user->id,
|
||||
'action' => 'document.imported',
|
||||
'auditable_type' => Document::class,
|
||||
'auditable_id' => $document->id,
|
||||
'old_values' => null,
|
||||
'new_values' => ['title' => $item['title']],
|
||||
'ip_address' => '127.0.0.1',
|
||||
'user_agent' => 'CLI Import',
|
||||
]);
|
||||
|
||||
$this->info(" ✓ Created document ID: {$document->id}");
|
||||
}
|
||||
|
||||
protected function getManifestExample(): string
|
||||
{
|
||||
return <<<'JSON'
|
||||
{
|
||||
"documents": [
|
||||
{
|
||||
"file": "bylaws.pdf",
|
||||
"title": "協會章程",
|
||||
"category": "association-bylaws",
|
||||
"document_number": "2024-001",
|
||||
"description": "協會章程修正版",
|
||||
"access_level": "members",
|
||||
"version_notes": "Initial import"
|
||||
},
|
||||
{
|
||||
"file": "meeting-2024-01.pdf",
|
||||
"title": "2024年1月會議記錄",
|
||||
"category": "meeting-minutes",
|
||||
"access_level": "members"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user