Files
opentextsummaries/app/Console/Commands/SyncBookFromGutendex.php
T

135 lines
4.7 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Jobs\ImportBookFromGutendex;
use App\Models\Book;
use Illuminate\Console\Command;
class SyncBookFromGutendex extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'gutendex:sync-book
{gutenberg_id : The Gutenberg book ID to import}
{--force : Force re-import even if book exists}
{--no-summary : Skip summary generation}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import or update a specific book from Gutendex by its ID';
/**
* Execute the console command.
*/
public function handle(): int
{
$gutenbergId = (int) $this->argument('gutenberg_id');
$force = $this->option('force');
$generateSummary = !$this->option('no-summary');
if ($gutenbergId <= 0) {
$this->error('Invalid Gutenberg ID. Must be a positive integer.');
return self::FAILURE;
}
$this->info("Syncing book from Gutendex (ID: {$gutenbergId})");
$this->newLine();
// Check if book already exists
$existingBook = Book::where('gutenberg_id', $gutenbergId)->first();
if ($existingBook && !$force) {
$this->warn('Book already exists in the database!');
$this->newLine();
$this->table(
['Field', 'Value'],
[
['Database ID', $existingBook->id],
['Title', $existingBook->title],
['Author', $existingBook->author],
['Slug', $existingBook->slug],
['Category', $existingBook->category->name ?? 'N/A'],
['Has Summary', $existingBook->summary ? 'Yes' : 'No'],
['Summary Status', $existingBook->summary->processing_status ?? 'N/A'],
]
);
$this->newLine();
if (!$this->confirm('Use --force to re-import. Continue anyway?', false)) {
$this->info('Operation cancelled.');
return self::SUCCESS;
}
// Delete existing book to re-import
$this->warn('Deleting existing book...');
$existingBook->delete();
$this->info('✓ Existing book deleted.');
$this->newLine();
}
// Fetch book info from Gutendex first to show details
$this->info('Fetching book details from Gutendex...');
$gutendexClient = app(\App\Services\GutendexClient::class);
$gutendexBook = $gutendexClient->getBook($gutenbergId);
if (!$gutendexBook) {
$this->error("Failed to fetch book {$gutenbergId} from Gutendex API.");
$this->comment('The book may not exist or the API may be unavailable.');
return self::FAILURE;
}
// Display book info
$this->info('✓ Book found on Gutendex');
$this->newLine();
$this->table(
['Field', 'Value'],
[
['Gutenberg ID', $gutendexBook->id],
['Title', $gutendexBook->title],
['Author(s)', $gutendexBook->getAuthorNamesString()],
['Language', $gutendexBook->getPrimaryLanguage()],
['Public Domain', $gutendexBook->isPublicDomain() ? 'Yes' : 'No'],
['Plain Text Available', $gutendexBook->getPlainTextUrl() ? 'Yes' : 'No'],
['Download Count', number_format($gutendexBook->downloadCount)],
]
);
$this->newLine();
// Validate book
if (!$gutendexBook->isPublicDomain()) {
$this->error('This book is not in the public domain and cannot be imported.');
return self::FAILURE;
}
if (!$gutendexBook->getPlainTextUrl()) {
$this->error('This book does not have a plain text version available.');
return self::FAILURE;
}
// Dispatch import job
$this->info('Dispatching import job...');
ImportBookFromGutendex::dispatch($gutenbergId, $generateSummary);
$this->newLine();
$this->info('✓ Import job dispatched successfully!');
$this->newLine();
$this->comment('The book will be imported in the background.');
$this->comment('Run the queue worker: php artisan queue:work');
if ($generateSummary) {
$this->comment('Summary will be generated automatically after import.');
} else {
$this->comment('Summary generation was skipped (--no-summary flag).');
}
return self::SUCCESS;
}
}