Add command to reclassify document content
This commit is contained in:
138
app/Console/Commands/ReclassifyDocumentContent.php
Normal file
138
app/Console/Commands/ReclassifyDocumentContent.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Article;
|
||||
use App\Models\ArticleCategory;
|
||||
use App\Services\SiteRevalidationService;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ReclassifyDocumentContent extends Command
|
||||
{
|
||||
protected $signature = 'articles:reclassify-document-content {--dry-run : Preview changes without writing to database}';
|
||||
|
||||
protected $description = 'Reclassify document-type articles into real documents vs story/blog content';
|
||||
|
||||
/**
|
||||
* Keep as document resources.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private array $keepDocumentSlugs = [
|
||||
'whisper-colab',
|
||||
'document-ef6231ce',
|
||||
'document-d34b35ab',
|
||||
];
|
||||
|
||||
/**
|
||||
* Move from document to blog/story.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
private array $moveToStorySlugs = [
|
||||
'document-b81734e3',
|
||||
'document-2f8fad62',
|
||||
'document-25e793fb',
|
||||
'document-48ec7f25',
|
||||
'document-f68da0b8',
|
||||
'document-a8bdf6d9',
|
||||
'document-694e4dd6',
|
||||
'document-d0608b86',
|
||||
'document-163bc74d',
|
||||
'document-ef370202',
|
||||
];
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$dryRun = (bool) $this->option('dry-run');
|
||||
|
||||
$allSlugs = array_values(array_unique(array_merge($this->keepDocumentSlugs, $this->moveToStorySlugs)));
|
||||
$articles = Article::query()
|
||||
->whereIn('slug', $allSlugs)
|
||||
->get()
|
||||
->keyBy('slug');
|
||||
|
||||
$missingSlugs = array_values(array_diff($allSlugs, $articles->keys()->all()));
|
||||
|
||||
$documentCategory = ArticleCategory::firstOrCreate(
|
||||
['slug' => 'document'],
|
||||
['name' => '協會文件', 'sort_order' => 20]
|
||||
);
|
||||
|
||||
$storyCategory = ArticleCategory::firstOrCreate(
|
||||
['slug' => 'story'],
|
||||
['name' => '故事', 'sort_order' => 30]
|
||||
);
|
||||
|
||||
$this->newLine();
|
||||
$this->info('Reclassification plan');
|
||||
$this->line(' Keep as document: '.count($this->keepDocumentSlugs));
|
||||
$this->line(' Move to story/blog: '.count($this->moveToStorySlugs));
|
||||
$this->line(' Found in DB: '.$articles->count());
|
||||
|
||||
if (! empty($missingSlugs)) {
|
||||
$this->warn('Missing slugs in DB: '.implode(', ', $missingSlugs));
|
||||
}
|
||||
|
||||
$this->newLine();
|
||||
$this->table(
|
||||
['Slug', 'Current Type', 'Target Type', 'Target Category'],
|
||||
collect($allSlugs)->map(function (string $slug) use ($articles) {
|
||||
$article = $articles->get($slug);
|
||||
$targetIsDocument = in_array($slug, $this->keepDocumentSlugs, true);
|
||||
|
||||
return [
|
||||
$slug,
|
||||
$article?->content_type ?? '(missing)',
|
||||
$targetIsDocument ? Article::CONTENT_TYPE_DOCUMENT : Article::CONTENT_TYPE_BLOG,
|
||||
$targetIsDocument ? 'document' : 'story',
|
||||
];
|
||||
})->all()
|
||||
);
|
||||
|
||||
if ($dryRun) {
|
||||
$this->newLine();
|
||||
$this->comment('Dry run only. No database updates were applied.');
|
||||
|
||||
return static::SUCCESS;
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($articles, $documentCategory, $storyCategory): void {
|
||||
foreach ($this->keepDocumentSlugs as $slug) {
|
||||
$article = $articles->get($slug);
|
||||
if (! $article) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$article->update(['content_type' => Article::CONTENT_TYPE_DOCUMENT]);
|
||||
$article->categories()->sync([$documentCategory->id]);
|
||||
}
|
||||
|
||||
foreach ($this->moveToStorySlugs as $slug) {
|
||||
$article = $articles->get($slug);
|
||||
if (! $article) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$article->update(['content_type' => Article::CONTENT_TYPE_BLOG]);
|
||||
$article->categories()->sync([$storyCategory->id]);
|
||||
}
|
||||
});
|
||||
|
||||
$revalidated = 0;
|
||||
foreach ($articles as $article) {
|
||||
if ($article->isPublished()) {
|
||||
SiteRevalidationService::revalidateArticle($article->slug);
|
||||
$revalidated++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->newLine();
|
||||
$this->info('Reclassification completed.');
|
||||
$this->line(' Updated articles: '.$articles->count());
|
||||
$this->line(' Revalidation requests sent: '.$revalidated);
|
||||
|
||||
return static::SUCCESS;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user