147 lines
4.6 KiB
PHP
147 lines
4.6 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use App\Models\Article;
|
|
use App\Models\ArticleCategory;
|
|
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;
|
|
$revalidateServiceClass = '\\App\\Services\\SiteRevalidationService';
|
|
$canRevalidate = class_exists($revalidateServiceClass);
|
|
|
|
if (! $canRevalidate) {
|
|
$this->warn('SiteRevalidationService not found. Skipping cache revalidation.');
|
|
}
|
|
|
|
foreach ($articles as $article) {
|
|
if (! $article->isPublished() || ! $canRevalidate) {
|
|
continue;
|
|
}
|
|
|
|
$revalidateServiceClass::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;
|
|
}
|
|
}
|