feat(comment): 게시글 댓글 CRUD 기능 추가
- 댓글 라우트 추가 (store, update, destroy) - PostService에 댓글 관리 메서드 추가 - PostController에 댓글 컨트롤러 메서드 추가 - 게시글 상세 페이지에 댓글 섹션 UI 추가 (AlpineJS) - 계층형 댓글 지원 (부모/대댓글) - BoardComment 모델 추가 - HTMLPurifier 패키지 및 설정 추가 - 게시글 목록에 첨부파일/댓글 수 표시 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Boards\Board;
|
||||
use App\Models\Boards\BoardComment;
|
||||
use App\Models\Boards\Post;
|
||||
use App\Services\PostService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -162,7 +163,10 @@ public function show(string $boardCode, Post $post, Request $request): View|Redi
|
||||
// 커스텀 필드 값
|
||||
$customFieldValues = $post->getCustomFieldsArray();
|
||||
|
||||
return view('posts.show', compact('board', 'post', 'adjacent', 'customFieldValues'));
|
||||
// 댓글 목록
|
||||
$comments = $this->postService->getComments($post);
|
||||
|
||||
return view('posts.show', compact('board', 'post', 'adjacent', 'customFieldValues', 'comments'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,4 +432,99 @@ public function deleteFile(string $boardCode, Post $post, int $fileId, Request $
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 400);
|
||||
}
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Comment Management
|
||||
// =========================================================================
|
||||
|
||||
/**
|
||||
* 댓글 작성
|
||||
*/
|
||||
public function storeComment(string $boardCode, Post $post, Request $request): RedirectResponse
|
||||
{
|
||||
$board = $this->resolveBoard($boardCode, $request);
|
||||
|
||||
// 게시판 일치 확인
|
||||
if ($post->board_id !== $board->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
// 비밀글 접근 권한 확인
|
||||
if (! $post->canAccess(auth()->user())) {
|
||||
return back()->with('error', '댓글을 작성할 수 없습니다.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'content' => 'required|string|max:1000',
|
||||
'parent_id' => 'nullable|integer|exists:board_comments,id',
|
||||
]);
|
||||
|
||||
$this->postService->createComment($post, $validated);
|
||||
|
||||
return redirect()
|
||||
->route('boards.posts.show', [$board->board_code, $post, 't' => $board->tenant_id])
|
||||
->with('success', '댓글이 작성되었습니다.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정
|
||||
*/
|
||||
public function updateComment(string $boardCode, Post $post, BoardComment $comment, Request $request): RedirectResponse
|
||||
{
|
||||
$board = $this->resolveBoard($boardCode, $request);
|
||||
|
||||
// 게시판 일치 확인
|
||||
if ($post->board_id !== $board->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
// 댓글-게시글 일치 확인
|
||||
if ($comment->post_id !== $post->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
// 수정 권한 확인 (작성자 또는 관리자)
|
||||
if ($comment->user_id !== auth()->id() && ! auth()->user()->hasRole(['admin', 'super-admin'])) {
|
||||
return back()->with('error', '수정 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'content' => 'required|string|max:1000',
|
||||
]);
|
||||
|
||||
$this->postService->updateComment($comment, $validated);
|
||||
|
||||
return redirect()
|
||||
->route('boards.posts.show', [$board->board_code, $post, 't' => $board->tenant_id])
|
||||
->with('success', '댓글이 수정되었습니다.');
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제
|
||||
*/
|
||||
public function destroyComment(string $boardCode, Post $post, BoardComment $comment, Request $request): RedirectResponse
|
||||
{
|
||||
$board = $this->resolveBoard($boardCode, $request);
|
||||
|
||||
// 게시판 일치 확인
|
||||
if ($post->board_id !== $board->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
// 댓글-게시글 일치 확인
|
||||
if ($comment->post_id !== $post->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
// 삭제 권한 확인 (작성자 또는 관리자)
|
||||
if ($comment->user_id !== auth()->id() && ! auth()->user()->hasRole(['admin', 'super-admin'])) {
|
||||
return back()->with('error', '삭제 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$this->postService->deleteComment($comment);
|
||||
|
||||
return redirect()
|
||||
->route('boards.posts.show', [$board->board_code, $post, 't' => $board->tenant_id])
|
||||
->with('success', '댓글이 삭제되었습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user