관리자 글 링크 참조 확인 추가
This commit is contained in:
@@ -109,6 +109,36 @@ const mapAdminPostSummaryRow = (row) => ({
|
||||
tags: row.tags || []
|
||||
})
|
||||
|
||||
/**
|
||||
* 정규식 특수 문자를 이스케이프한다.
|
||||
* @param {string} value - 원본 문자열
|
||||
* @returns {string} 이스케이프된 문자열
|
||||
*/
|
||||
const escapeRegExp = (value) => String(value || '').replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
|
||||
/**
|
||||
* 게시물 공개 링크 참조 정규식을 생성한다.
|
||||
* @param {string} slug - 게시물 슬러그
|
||||
* @returns {RegExp} 게시물 링크 정규식
|
||||
*/
|
||||
const createPostLinkReferencePattern = (slug) => {
|
||||
return new RegExp(`(?:^|[\\s("'\\[])(?:https?:\\/\\/[^/\\s)"'<>]+)?\\/post\\/${escapeRegExp(slug)}(?=$|[\\s)"'<>?#/])`, 'gi')
|
||||
}
|
||||
|
||||
/**
|
||||
* 본문에서 특정 게시물 링크 참조 개수를 계산한다.
|
||||
* @param {string} content - 게시물 본문
|
||||
* @param {string} slug - 참조 대상 슬러그
|
||||
* @returns {number} 참조 개수
|
||||
*/
|
||||
const countPostLinkReferences = (content, slug) => {
|
||||
if (!slug) {
|
||||
return 0
|
||||
}
|
||||
|
||||
return [...String(content || '').matchAll(createPostLinkReferencePattern(slug))].length
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 글 목록 페이지 표시 개수를 정규화한다.
|
||||
* @param {unknown} value - 요청 표시 개수
|
||||
@@ -816,6 +846,76 @@ export const listMediaReferencePosts = async () => {
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물을 링크하고 있는 관리자 게시물 목록을 조회한다.
|
||||
* @param {string} id - 참조 대상 게시물 ID
|
||||
* @returns {Promise<{ target: { id: string, title: string, slug: string }, posts: Array<{ id: string, title: string, slug: string, status: string, publishedAt: string | null, updatedAt: string, referenceCount: number }> } | null>} 참조 게시물 목록
|
||||
*/
|
||||
export const listAdminPostReferences = async (id) => {
|
||||
const sql = getPostgresClient()
|
||||
const target = await getAdminPostById(id)
|
||||
|
||||
if (!target) {
|
||||
return null
|
||||
}
|
||||
|
||||
const mapReferenceRow = (post) => ({
|
||||
id: post.id,
|
||||
title: toAdminPostFormTitle(post.title),
|
||||
slug: post.slug,
|
||||
status: post.status,
|
||||
publishedAt: post.published_at
|
||||
? post.published_at.toISOString()
|
||||
: post.publishedAt || null,
|
||||
updatedAt: post.updated_at
|
||||
? post.updated_at.toISOString()
|
||||
: post.updatedAt || '',
|
||||
referenceCount: countPostLinkReferences(post.content, target.slug)
|
||||
})
|
||||
|
||||
if (!sql) {
|
||||
const posts = getSamplePosts()
|
||||
.filter((post) => post.id !== target.id)
|
||||
.map(mapReferenceRow)
|
||||
.filter((post) => post.referenceCount > 0)
|
||||
|
||||
return {
|
||||
target: {
|
||||
id: target.id,
|
||||
title: target.title,
|
||||
slug: target.slug
|
||||
},
|
||||
posts
|
||||
}
|
||||
}
|
||||
|
||||
const rows = await sql`
|
||||
SELECT
|
||||
id,
|
||||
title,
|
||||
slug,
|
||||
status,
|
||||
published_at,
|
||||
updated_at,
|
||||
content
|
||||
FROM posts
|
||||
WHERE id <> ${target.id}
|
||||
AND content ILIKE ${`%/post/${target.slug}%`}
|
||||
ORDER BY updated_at DESC
|
||||
`
|
||||
|
||||
return {
|
||||
target: {
|
||||
id: target.id,
|
||||
title: target.title,
|
||||
slug: target.slug
|
||||
},
|
||||
posts: rows
|
||||
.map(mapReferenceRow)
|
||||
.filter((post) => post.referenceCount > 0)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 관리자 게시물 상세 조회
|
||||
* @param {string} id - 게시물 ID
|
||||
|
||||
24
server/routes/admin/api/posts/[id]/references.get.js
Normal file
24
server/routes/admin/api/posts/[id]/references.get.js
Normal file
@@ -0,0 +1,24 @@
|
||||
import { createError, getRouterParam } from 'h3'
|
||||
import { requireAdminSession } from '../../../../../utils/admin-auth'
|
||||
import { listAdminPostReferences } from '../../../../../repositories/content-repository'
|
||||
|
||||
/**
|
||||
* 관리자 게시물 참조 목록 API
|
||||
* @param {import('h3').H3Event} event - 요청 이벤트
|
||||
* @returns {Promise<{ target: { id: string, title: string, slug: string }, posts: Array }>} 참조 목록
|
||||
*/
|
||||
export default defineEventHandler(async (event) => {
|
||||
requireAdminSession(event)
|
||||
|
||||
const id = getRouterParam(event, 'id')
|
||||
const references = await listAdminPostReferences(id)
|
||||
|
||||
if (!references) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
message: '게시물을 찾을 수 없습니다.'
|
||||
})
|
||||
}
|
||||
|
||||
return references
|
||||
})
|
||||
Reference in New Issue
Block a user