fix: [attach] 短代码跨文章全局解析 + 缺失残留清理;损坏附件导入降级不中断;media 导入幂等;sablog:import 支持 sqlite 老库 + 5 个导入自动化测试
This commit is contained in:
@@ -16,6 +16,19 @@ class AttachmentImporter
|
||||
*/
|
||||
public function create(int $postId, array $row, ?string $attachmentsDir, bool $syncNow): Media
|
||||
{
|
||||
$legacyId = (int) ($row['attachmentid'] ?? 0);
|
||||
|
||||
// 幂等:同一老附件已成功导入过则直接复用
|
||||
$existing = Media::query()
|
||||
->where('collection_name', 'attachments')
|
||||
->where('custom_properties->legacy_attachmentid', $legacyId)
|
||||
->latest('id')
|
||||
->first();
|
||||
|
||||
if ($existing && ! $existing->getCustomProperty('pending_sync')) {
|
||||
return $existing;
|
||||
}
|
||||
|
||||
$post = Post::find($postId);
|
||||
|
||||
// 游离附件(articleid=0 或对应文章不存在)统一挂到 id=0 占位文章上
|
||||
@@ -36,16 +49,39 @@ class AttachmentImporter
|
||||
$source = $this->locateSource($row['filepath'] ?? null, $attachmentsDir);
|
||||
|
||||
if ($source && $syncNow) {
|
||||
$media = $post->addMedia($source)
|
||||
->preservingOriginal()
|
||||
->withCustomProperties($properties)
|
||||
->usingFileName(basename($row['filename']) ?: basename($source))
|
||||
->toMediaCollection('attachments', MediaDisk::name());
|
||||
try {
|
||||
$media = $post->addMedia($source)
|
||||
->preservingOriginal()
|
||||
->withCustomProperties($properties)
|
||||
->usingFileName(basename($row['filename']) ?: basename($source))
|
||||
->toMediaCollection('attachments', MediaDisk::name());
|
||||
|
||||
$media->setCustomProperty('pending_sync', false);
|
||||
$media->save();
|
||||
$media->setCustomProperty('pending_sync', false);
|
||||
$media->save();
|
||||
|
||||
return $media;
|
||||
return $media;
|
||||
} catch (\Throwable $e) {
|
||||
// addMedia 可能已插入记录并保存文件,仅缩略图生成失败:找回该记录标记完成
|
||||
$existing = Media::query()
|
||||
->where('collection_name', 'attachments')
|
||||
->where('custom_properties->legacy_attachmentid', (int) ($row['attachmentid'] ?? 0))
|
||||
->latest('id')
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
$existing->setCustomProperty('pending_sync', false);
|
||||
$existing->save();
|
||||
|
||||
return $existing;
|
||||
}
|
||||
|
||||
// 文件损坏无法入库时降级为 pending,不中断整批导入
|
||||
\Illuminate\Support\Facades\Log::warning('附件导入失败,已降级为待同步', [
|
||||
'attachment' => $row['attachmentid'] ?? null,
|
||||
'file' => $source,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->createPendingRecord($post->id, $row, $properties);
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
namespace App\Blog\Services;
|
||||
|
||||
use App\Models\Post;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use League\CommonMark\Environment\Environment;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
|
||||
use League\CommonMark\MarkdownConverter;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
|
||||
class PostContentRenderer
|
||||
{
|
||||
@@ -63,9 +65,16 @@ class PostContentRenderer
|
||||
return $html;
|
||||
}
|
||||
|
||||
$mediaItems = $post->getMedia('attachments');
|
||||
$byLegacyId = $mediaItems->keyBy(fn ($m) => (int) $m->getCustomProperty('legacy_attachmentid'));
|
||||
$ordered = $mediaItems->values();
|
||||
// 短代码引用的是 sablog 全局附件 id,可能属于其他文章,需要全局查
|
||||
$byLegacyId = Cache::remember('attach.legacy_ids', now()->addHour(), function () {
|
||||
return Media::query()
|
||||
->where('collection_name', 'attachments')
|
||||
->get()
|
||||
->keyBy(fn ($m) => (int) $m->getCustomProperty('legacy_attachmentid'));
|
||||
});
|
||||
|
||||
// 当前文章媒体用于索引回退
|
||||
$ordered = $post->getMedia('attachments')->values();
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$full = $match[0];
|
||||
@@ -80,6 +89,8 @@ class PostContentRenderer
|
||||
}
|
||||
|
||||
if (! $media) {
|
||||
// 找不到媒体时移除残留短代码,避免把 [attach=999] 当正文显示
|
||||
$html = str_replace($full, '', $html);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user