boardModel = new Board(); $this->boardMetaModel = new BoardMeta(); $this->postModel = new Post(); $this->commentModel = new Comment(); $this->commentMetaModel = new CommentMeta(); $this->commentHistoryModel = new CommentHistory(); $this->commentLikeModel = new CommentLike(); $this->commentBlameModel = new CommentBlame(); $this->commentDeletedModel = new CommentDeleted(); $this->userModel = new User(); $this->fileLib = new FileLib(); $this->emailLib = new EmailLib(); $this->editorImageModel = new EditorImage(); } public function meta(int $commentID): ?CommentMeta { return $this->commentMetaModel->getAllMeta($commentID); } public function find(int $commentID): Comment { return $this->_filter($this->commentModel->get($commentID)); } /** * 댓글 전체 수 */ public function total(int $postID): int { return $this->commentModel->total($postID); } /** * 전체 댓글 목록 조회 */ public function list(string $code, int $postID, SearchData $params): object { $comments = $this->commentModel->getList($code, $postID, $params->page, $params->offset, $params->perPage, $params->sort); if($comments->total > 0) { $num = listNum($comments->total, $params->page, $params->perPage); foreach($comments->list as $i => $row) { $row = $this->commentModel->newInstance(get_object_vars($row), true); $row->num = $num--; $comments->list[$i] = $this->_filter($row); } } return $comments; } /** * 회원 댓글 조회 */ public function userList(int $userID, SearchData $params): object { $comments = $this->commentModel->getUserList($userID, $params); if($comments->total > 0) { $num = listNum($comments->total, $params->page, $params->perPage); foreach($comments->list as $i => $row) { $row = $this->commentModel->newInstance(get_object_vars($row), true); $row->num = $num--; $row->page = $this->commentModel->findPageNumber($row->id, $params->perPage); $comments->list[$i] = $this->_filter($row); } } return $comments; } /** * 댓글 정보 가공 */ private function _filter(Comment $comment): Comment { if(!$comment->exists) { return $comment; } $boardMeta = $this->boardMetaModel->getAllMeta($comment->board_id); $comment->user->thumb = $this->profileThumbSrc($comment->user->thumb); $comment->viewURL = route('board.post.view', [ $comment->board->code, $comment->post_id ]); // 익명 게시판일 경우 if( $boardMeta->item('use_anonymous', 0) && (!$comment->user->is_admin || !$boardMeta->item('anonymous_except_admin', 0)) && $comment->user->id ) { $comment->username = $this->createAnonymousName( $boardMeta->item('anonymous_name'), $comment->user->id, $comment->post_id ); } // 댓글 설정 정보 $commentMeta = $this->meta($comment->id); // 관리자에 의한 삭제 $comment->isBlind = $commentMeta->item('is_blind', 0); // IP 표시 형식 $showCommentIP = $boardMeta->item('show_comment_ip'); // 노출 방법 if ($showCommentIP) { $ipDisplayStyle = ($showCommentIP == 2 || IS_ADMIN ? '1111' : config('ip_display_style')); // IP 형식 $comment->ipAddress = $this->ipAddrMasking($comment->ip_address, $ipDisplayStyle); } // 신고 누적으로 숨김 $comment->isBlame = false; if($commentBlameBlindCount = $boardMeta->item('comment_blame_blind_count', 0)) { $comment->isBlame = ($comment->blame >= $commentBlameBlindCount); } // 좋아요 $comment->isLike = $this->commentLikeModel->isAlready($comment, UID, LIKE); // 싫어요 $comment->isDislike = $this->commentLikeModel->isAlready($comment,UID, DISLIKE); // 작성일시 $comment->createdAt = $this->dateFormat($comment->created_at); return $comment; } /** * 댓글 등록 */ public function register(CommentRequest $request, ResponseData $response): ResponseData { DB::beginTransaction(); try { $user = $request->user(); $boardMeta = $request->boardMeta; $boardID = intval($request->post('bid')); $postID = intval($request->post('pid')); $content = $this->getContent($request); // 댓글 정보 저장 $comment = $this->commentModel->register([ 'board_id' => $boardID, 'post_id' => $postID, 'user_id' => $user?->id, 'parent_id' => null, 'is_reply' => 0, 'content' => $content, 'sid' => $user?->sid, 'username' => $request->post('username', $user?->name), 'email' => $user?->email, 'password' => $request->post('password'), 'reply' => 0, 'like' => 0, 'dislike' => 0, 'blame' => 0, 'device_type' => DEVICE_TYPE, 'is_secret' => ($boardMeta->item('use_comment_secret', 0) == '2' ? 1 : $request->post('is_secret', 0)), 'is_delete' => 0, 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT, 'deleted_at' => null, 'updated_at' => null, 'created_at' => now() ]); // 게시판 댓글 수 갱신 $this->boardModel->updateCommentRows($boardID); // 게시글 댓글 수 갱신 $this->postModel->updateCommentRows($postID); // 댓글 Meta 저장 $this->commentMetaModel->save($comment->id, [ 'is_blind' => 0, 'exec_blind_key' => null ]); // 댓글 기록 저장 if ($boardMeta->item('use_comment_history', 0)) { $this->commentHistoryModel->register($comment, '댓글 등록'); } $response->comment = $comment; DB::commit(); } catch (Exception $e) { $response = $response::fromException($e); DB::rollBack(); } return $response; } /** * 댓글 수정 */ public function updater(CommentRequest $request, ResponseData $response): ResponseData { DB::beginTransaction(); try { $user = $request->user(); $boardMeta = $request->boardMeta; $boardID = intval($request->post('bid')); $postID = intval($request->post('pid')); $commentID = intval($request->post('cid')); $content = $this->getContent($request); // 댓글 기록 저장 if($boardMeta->item('use_comment_history', 0)) { $this->commentHistoryModel->updater($request->comment, '댓글 수정'); } // 댓글 수정 $comment = $this->commentModel->updater($commentID, [ 'board_id' => $boardID, 'post_id' => $postID, 'user_id' => $user?->id, 'content' => $content, 'is_secret' => $request->post('is_secret', 0), 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT, 'updated_at' => now() ]); // 댓글 작성시 글 수정 시각 갱신 if($boardMeta->item('update_order_on_comment', 0)) { $this->postModel->updater($postID, [ 'updated_at' => now() ]); } $response->comment = $comment; DB::commit(); } catch (Exception $e) { $response = $response::fromException($e); DB::rollBack(); } return $response; } /** * 댓글 답글 */ public function reply(CommentRequest $request, ResponseData $response): ResponseData { DB::beginTransaction(); try { $user = $request->user(); $boardMeta = $request->boardMeta; $boardID = intval($request->post('bid')); $postID = intval($request->post('pid')); $commentID = intval($request->post('cid')); $content = $this->getContent($request); // 답글 저장 $newComment = $this->commentModel->reply($commentID, [ 'board_id' => $boardID, 'post_id' => $postID, 'user_id' => $user?->id, 'parent_id' => null, 'is_reply' => 0, 'content' => $content, 'sid' => $user?->sid, 'username' => $request->post('username', $user?->name), 'email' => $user?->email, 'password' => $request->post('password'), 'reply' => 0, 'like' => 0, 'dislike' => 0, 'blame' => 0, 'device_type' => DEVICE_TYPE, 'is_secret' => ($boardMeta->item('use_comment_secret', 0) == '2' ? 1 : $request->post('is_secret', 0)), 'is_delete' => 0, 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT, 'deleted_at' => null, 'updated_at' => null, 'created_at' => now() ]); // 부모 댓글 답변 여부 등록 $this->commentModel->updater($commentID, [ 'is_reply' => 1 ]); // 게시판 댓글 수 갱신 $this->boardModel->updateCommentRows($boardID); // 게시글 댓글 수 갱신 $this->postModel->updateCommentRows($postID); // 부모 댓글 수 갱신 $this->commentModel->updateCommentRows($commentID); // 댓글 Meta 저장 $this->commentMetaModel->save($newComment->id, [ 'is_blind' => 0, 'exec_blind_key' => null ]); // 답글 등록 기록 if($boardMeta->item('use_comment_history', 0)) { $this->commentHistoryModel->register($newComment, '답글 등록'); } $response->comment = $newComment; DB::commit(); } catch (Exception $e) { $response = $response::fromException($e); DB::rollBack(); } return $response; } /** * 댓글 삭제 */ public function delete(Request $request, ResponseData $response): ResponseData { DB::beginTransaction(); try { $comment = $request->comment; // 댓글 존재 확인 if (!$comment->exists) { throw new Exception('댓글이 존재 하지 않습니다.'); } $userID = $request->user()?->id; // 댓글 삭제 여부 승인 $this->commentModel->updater($comment->id, [ 'is_delete' => 1, 'deleted_at' => now() ]); // 댓글 삭제 정보 추가 $this->commentDeletedModel->register([ 'board_id' => $comment->board_id, 'post_id' => $comment->post_id, 'comment_id' => $comment->id, 'user_id' => $userID, 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT, 'created_at' => now() ]); // 게시판 댓글 수 갱신 $this->boardModel->updateCommentRows($comment->board_id); // 게시판 댓글 수 갱신 $this->postModel->updateCommentRows($comment->post_id); // 부모 댓글 수 갱신 $this->commentModel->updateCommentRows($comment->id); $response->comment = $comment; DB::commit(); } catch (Exception $e) { $response = $response::fromException($e); DB::rollBack(); } return $response; } /** * 댓글 신고 */ public function blame(Request $request, ResponseData $response): ResponseData { DB::beginTransaction(); try { $comment = $this->commentModel->findOrNew( $request->post('cid') ); // 댓글 존재 확인 if (!$comment->exists) { throw new Exception('댓글이 존재 하지 않습니다.'); } $userID = $request->user()->id; // 이미 신고했는지 확인 if ($this->commentBlameModel->isAlready($comment, $userID)) { throw new Exception('이미 신고하셨습니다.'); } $this->commentBlameModel->register([ 'board_id' => $comment->board_id, 'post_id' => $comment->post_id, 'comment_id' => $comment->id, 'user_id' => $userID, 'type' => $request->post('type'), 'reason' => $request->post('reason'), 'status' => 0, 'memo' => null, 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT, 'created_at' => now() ]); $this->commentModel->increaseBlame($comment->id); DB::commit(); } catch (Exception $e) { $response = $response::fromException($e); DB::rollBack(); } return $response; } /** * 댓글 좋아요 */ public function like(Request $request, ResponseData $response): ResponseData { DB::beginTransaction(); try { $comment = $this->commentModel->findOrNew( $request->post('cid') ); // 댓글 존재 확인 if (!$comment->exists) { throw new Exception('댓글이 존재 하지 않습니다.'); } $userID = $request->user()->id; $saveData = [ 'board_id' => $comment->board_id, 'post_id' => $comment->post_id, 'comment_id' => $comment->id, 'user_id' => $userID, 'type' => LIKE, 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT, 'created_at' => now() ]; $likeInfo = $this->commentLikeModel->info($comment, $userID); if ($likeInfo->exists) { $this->commentLikeModel->remove($comment, $userID); if ($likeInfo->type == LIKE) { $this->commentModel->decreaseLike($comment->id); } else if ($likeInfo->type == DISLIKE) { $this->commentLikeModel->register($saveData); $this->commentModel->increaseLike($comment->id); $this->commentModel->decreaseDisLike($comment->id); } } else { $this->commentLikeModel->register($saveData); $this->commentModel->increaseLike($comment->id); } $response->comment = $comment; DB::commit(); } catch (Exception $e) { $response = $response::fromException($e); DB::rollBack(); } return $response; } /** * 댓글 싫어요 */ public function dislike(Request $request, ResponseData $response): ResponseData { DB::beginTransaction(); try { $comment = $this->commentModel->findOrNew( $request->post('cid') ); // 댓글 존재 확인 if (!$comment->exists) { throw new Exception('댓글이 존재 하지 않습니다.'); } $userID = $request->user()->id; $saveData = [ 'board_id' => $comment->board_id, 'post_id' => $comment->post_id, 'comment_id' => $comment->id, 'user_id' => $userID, 'type' => DISLIKE, 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT, 'created_at' => now() ]; $likeInfo = $this->commentLikeModel->info($comment, $userID); if ($likeInfo->exists) { $this->commentLikeModel->remove($comment, $userID); if ($likeInfo->type == DISLIKE) { $this->commentModel->decreaseDisLike($comment->id); } else if ($likeInfo->type == LIKE) { $this->commentLikeModel->register($saveData); $this->commentModel->increaseDisLike($comment->id); $this->commentModel->decreaseLike($comment->id); } } else { $this->commentLikeModel->register($saveData); $this->commentModel->increaseDisLike($comment->id); } $response->comment = $comment; DB::commit(); } catch (Exception $e) { $response = $response::fromException($e); DB::rollBack(); } return $response; } /** * 게시글에 내 댓글이 몇개인지 확인 */ public function userCommentRows(Post $post, User $user): int { return $this->commentModel->where([ ['board_id', $post->board_id], ['post_id', $post->id], ['user_id', $user->id], ])->count(); } /** * 댓글 에디터 내용 처리 */ private function getContent(CommentRequest $request): string { // 게시글 이미지 저장 $boardMeta = $request->boardMeta; $postID = $request->pid; $commentID = $this->commentModel->lastedKey(); $content = trim($request->post('content')); if ($boardMeta->use_personal) { $addPath = ($postID . DIRECTORY_SEPARATOR . $commentID); if ($boardMeta->save_external_image) { // link $content = $this->fileLib->saveImageFromUrl($content, UPLOAD_PATH_COMMENT, $addPath); } // blob $content = $this->fileLib->saveImageFromBlob($content, UPLOAD_PATH_COMMENT, $addPath); // 이미지 DB 기록 $images = $this->fileLib->getImageFromContent($content); if(count($images) > 0) { foreach($images as $img) { $this->editorImageModel->register([ 'target_type' => EDITOR_IMG_TYPE_2, 'target_id' => $addPath, 'user_id' => UID, 'origin_name' => $img->origin, 'file_name' => $img->name, 'file_path' => $img->path, 'file_url' => $img->url, 'file_size' => $img->size, 'file_type' => $img->type, 'width' => $img->width, 'height' => $img->height, 'ip_address' => IP_ADDRESS, 'user_agent' => USER_AGENT ]); } } } return $content; } /** * 댓글 경험치 지급 */ public function setUserExp(Comment $comment, User $user, int $type): bool { $boardMeta = $this->boardMetaModel->getAllMeta($comment->board_id); if (!$boardMeta->item('use_exp', 0)) { return false; } $column = MAP_EXP_TYPE[$type]; $content = MAP_EXP_CONTENT[$type]; $value = intval($boardMeta->{$column}); $relatedID = sprintf("%d-%d-%d", $comment->board_id, $comment->post_id, $comment->id); // 경험치 지급 구분 return (new Exp)->register([ 'user_id' => $user->id, 'content' => $content, 'value' => $value, 'type' => $type, 'related_id' => $relatedID, 'method' => request()->getMethod(), 'created_at' => now() ]); } /** * 게시글 관련 메일 발송 */ public function sendEmailNotify(Comment $comment, string $sendMailFormType): bool { if(!in_array($sendMailFormType, MAP_SEND_MAIL_TYPE)) { return false; } $post = $comment->post; $boardMeta = $this->boardMetaModel->getAllMeta($post->board_id); $sendMailType = str_replace('_form', '', $sendMailFormType); // 최고 관리자에게 발송 $admin = ($boardMeta->item($sendMailType . '_super_admin', 0) ? $this->userModel->getMaster() : null); // 게시글 작성자에게 발송 $postWriter = ($boardMeta->item($sendMailType . '_post_writer', 0) ? $post->user : null); // 댓글 작성자에게 발송 $commentWriter = ($boardMeta->item($sendMailType . '_comment_writer', 0) ? $comment->user : null); if(!$admin && !$postWriter && !$commentWriter) { return false; } // 1:1 문의 답변 완료 처리 $post->updater($post->id, [ 'is_reply' => 1 ]); return (new EmailLib)->send($sendMailFormType, $admin, $postWriter, $commentWriter); } }