Re-implement syncLinks and processLinks via WikiLinkResolver

syncLinks parses the default-locale content; processLinks resolves
each [[link]] against the current locale at render time. Link labels
preserve original spelling; destination resolves to the same document
in the current locale (with fallback).
This commit is contained in:
Yutaka Kurosaki
2026-05-10 12:25:19 +09:00
parent 7909c33074
commit 6d71f5fecf
2 changed files with 124 additions and 2 deletions
+66
View File
@@ -76,4 +76,70 @@ public function test_available_locales_lists_existing_translations(): void
sort($locales);
$this->assertSame(['en', 'fr', 'ja'], $locales);
}
public function test_sync_links_creates_outgoing_links_with_resolved_targets(): void
{
$target = Document::factory()->create(['default_locale' => 'en']);
$target->translations()->where('locale', 'en')->update(['title' => 'Target']);
$source = Document::factory()->create(['default_locale' => 'en']);
$source->translations()->where('locale', 'en')->update([
'content' => 'See [[Target]] for details.',
]);
$source->fresh('translations')->syncLinks();
$links = $source->fresh()->outgoingLinks;
$this->assertCount(1, $links);
$this->assertSame($target->id, $links->first()->target_document_id);
$this->assertSame('Target', $links->first()->target_title);
}
public function test_sync_links_records_unresolved_links_with_null_target(): void
{
$source = Document::factory()->create();
$source->translations()->first()->update([
'content' => 'Goes to [[NoSuchPage]].',
]);
$source->fresh('translations')->syncLinks();
$links = $source->fresh()->outgoingLinks;
$this->assertCount(1, $links);
$this->assertNull($links->first()->target_document_id);
}
public function test_process_links_replaces_wiki_link_with_anchor_keeping_label(): void
{
$target = Document::factory()->create(['default_locale' => 'en', 'slug' => 'target-doc']);
$target->translations()->where('locale', 'en')->update(['title' => 'Target']);
\Illuminate\Support\Facades\App::setLocale('ja');
\App\Models\DocumentTranslation::factory()->create([
'document_id' => $target->id,
'locale' => 'ja',
'title' => 'ターゲット',
]);
$source = Document::factory()->create();
$source->translations()->first()->update([
'rendered_html' => '<p>See [[Target]].</p>',
]);
$html = $source->fresh()->processLinks();
$this->assertStringContainsString('href="' . route('documents.show', 'target-doc') . '"', $html);
$this->assertStringContainsString('>Target<', $html); // label preserved
$this->assertStringContainsString('class="wiki-link"', $html);
}
public function test_process_links_marks_unresolved_links_as_new(): void
{
$source = Document::factory()->create();
$source->translations()->first()->update([
'rendered_html' => '<p>Click [[Ghost]].</p>',
]);
$html = $source->fresh()->processLinks();
$this->assertStringContainsString('wiki-link-new', $html);
}
}